2016-05-04 9 views
0

私は、日付範囲内のメンバーを返すレポートを作成するために取り組んでいます。関係(MEMBERS.relationship)列はメンバーの 'M'に等しく、メンバーシップタイプはTHENのいずれかで、この基準に一致するメンバーレコードごとに、CHKINSテーブルから指定された期間のチェックイン数を返す必要があります。チェックインごとにCHKINSテーブルに1つのエントリがあり、 'ischeckin'フィールドを有効なチェックインにするには 'True'に設定する必要があります。言い換えれば、John Doeは指定された期間10回施設にチェックインした。指定されたフィールドに値 '10'を加えた1つの行が返される必要があります。私が今構築しているものは、私に10の別々の行を与えます。テーブルBからの行数(テーブルAからの結果)

SELECT   
    EMPLOYEES.lname, EMPLOYEES.fname, 
    MEMBERS.fname AS Expr1, MEMBERS.scancode, MEMBERS.lname AS Expr2, 
    MEMBERTYPES.description, 
    MEMBERS.phone1, MEMBERS.phone2, MEMBERS.lastvisit, MEMBERS.email, 
    MEMBERS.datejoin, MEMBERS.dateexpire, MEMBERS.daterenewal, 
    CHKINS.checkin, SITES.sitename, MEMBERS.relationship, MEMBERS.mtypeid 
FROM    
    MEMBERS 
INNER JOIN 
    CHKINS ON MEMBERS.memid = CHKINS.memid 
INNER JOIN 
    EMPLOYEES ON MEMBERS.employeeid = EMPLOYEES.employeeid 
INNER JOIN 
    SITES ON MEMBERS.siteid = SITES.siteid 
INNER JOIN 
    MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid 
WHERE 
    (CHKINS.ischeckin = 'True') 
    AND (CHKINS.checkin BETWEEN @rvStartDate AND DATEADD(day, 45, @rvStartDate)) 
    AND (MEMBERS.relationship = 'M') 
    AND (MEMBERS.status = 'A') 
    AND (MEMBERS.mtypeid = '1' OR MEMBERS.mtypeid = '10' OR 
     MEMBERS.mtypeid = '12' OR MEMBERS.mtypeid = '22' OR 
     MEMBERS.mtypeid = '28' OR MEMBERS.mtypeid = '32' OR 
     MEMBERS.mtypeid = '33' OR MEMBERS.mtypeid = '34' OR 
     MEMBERS.mtypeid = '35' OR MEMBERS.mtypeid = '36' OR 
     MEMBERS.mtypeid = '40' OR MEMBERS.mtypeid = '48') 
    AND (MEMBERS.datejoin BETWEEN @rvStartDate AND @rvEndDate) 
+0

私は、 'memid'がマッチする' CHKINS'のレコード数を選択するサブクエリが必要であり、 'ischeckin'が' True'である必要があると思います。サブクエリを作成する方法を理解するのに役立つ必要がありますか? – Zack

+0

よろしくお願い致します!私はかなり新しく、まだ学びます。 – Merlin

+1

これはどのRDBMSですか? 'mysql'、' postgresql'、 'sql-server'、' oracle'、 'db2'のどれかを指定するタグを追加してください。 –

答えて

0

あなたは、ischeckinがどこにあるMEMBERS.memidに一致するレコードの数を選択し、あなたの選択リスト内のサブクエリを追加することにより、CHKINSテーブルから有効なチェックインの回数を得ることができTrue

SELECT EMPLOYEES.lname 
    ,EMPLOYEES.fname 
    ,MEMBERS.fname AS Expr1 
    ,MEMBERS.scancode 
    ,MEMBERS.lname AS Expr2 
    ,MEMBERTYPES.[description] 
    ,MEMBERS.phone1 
    ,MEMBERS.phone2 
    ,MEMBERS.lastvisit 
    ,MEMBERS.email 
    ,MEMBERS.datejoin 
    ,MEMBERS.dateexpire 
    ,MEMBERS.daterenewal 
    ,MEMBERS.relationship 
    ,MEMBERS.mtypeid 
    ,CHKINS.checkin 
    ,SITES.sitename 
    ,(SELECT COUNT(*) FROM CHKINS WHERE CHKINS.memid = MEMBERS.memid AND CHKINS.ischeckin = 'True') AS CheckinCount 
FROM MEMBERS 
    INNER JOIN CHKINS ON MEMBERS.memid = CHKINS.memid 
    INNER JOIN EMPLOYEES ON MEMBERS.employeeid = EMPLOYEES.employeeid 
    INNER JOIN SITES ON MEMBERS.siteid = SITES.siteid 
    INNER JOIN MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid 
WHERE (CHKINS.ischeckin = 'True') 
    AND (CHKINS.checkin BETWEEN @rvStartDate AND DATEADD(day, 45, @rvStartDate)) 
    AND (MEMBERS.relationship = 'M') 
    AND (MEMBERS.[status] = 'A') 
    AND (MEMBERS.mtypeid = '1' OR 
     MEMBERS.mtypeid = '10' OR 
     MEMBERS.mtypeid = '12' OR 
     MEMBERS.mtypeid = '22' OR 
     MEMBERS.mtypeid = '28' OR 
     MEMBERS.mtypeid = '32' OR 
     MEMBERS.mtypeid = '33' OR 
     MEMBERS.mtypeid = '34' OR 
     MEMBERS.mtypeid = '35' OR 
     MEMBERS.mtypeid = '36' OR 
     MEMBERS.mtypeid = '40' OR 
     MEMBERS.mtypeid = '48') 
    AND (MEMBERS.datejoin BETWEEN @rvStartDate AND @rvEndDate) 
1

データベーススキーマの機能をすべて把握していませんが、レポートに列を追加する場合は、いくつかの結合が必要でない限り、質問に答えているようです。基本的には、カウントを使ってグループを使用する場合、サブクエリよりもはるかに高速に実行する必要があります。あなたがまだあなたのコメントの1つで学んでいる/かなり新しいことを言っているのを見ている。私は自分の味のためにあなたの構造に関していくつかのことを周りに変えました。 1つの変更はテーブルの略語を使用することです。あなたがfromの領域にテーブルを置くときには、単にスペースを加え、次に省略形(例えば、メンバーの場合はm)を追加します。もう一方の薄い部分は、mtypidのORのリストをin文に切り替えています。これは本質的に同じことです。コメントには先行することに注意してください.SSMSのクエリウィンドウに次のコードを書き留めておけば、コードを読みやすくするためのヒントを見つけることができます。

グループを使用して複数の表を結合するときのトリックは、1対1と1対1の関係を理解することです。それが1対多であれば、例えば。 CHKINSテーブルの場合、それは他のテーブル(メンバータイプなど)のメンバーテーブルに1対1のみを使用することが重要です。カウントを使用する場合は、カウントにCHKINSの一意のIDを使用してください。あなたの質問がemployee、membertypes、またはsitesテーブルの中で何かを使うことについて尋ねなかったなら、メンバーとchckinsの間の直接的な1対多の関係を残すだけでそれらを削除することができます。その後、あなたが見たいと思っている関係の片側から離れているすべての列については、グループ内の列も含めます。

SELECT   
    FirstName = m.fname --m.fname AS Expr1 can chane to ,FirtsName = m.fname or ,m.fname AS FisrtName if you don't want Expr1 
    ,LastName = m.lname --m.lname AS Expr2 Again can replace Expr2 with something more meaninglfull if desired e.g. LastName (also is this exact same as e.lname ? do you want both?) 
    ,m.description 
    ,m.phone1 
    ,m.phone2 
    ,m.lastvisit 
    ,m.email 
    ,m.datejoin 
    ,m.dateexpire 
    ,m.daterenewal 
    ,m.relationship 
    ,m.mtypeid 
    ,m.status 
    ,CountOfCheckins = COUNT(*) --If you know the PrimaryKey for CHKINS you could aso do COUNT(DISNTINCT c.Id) 
FROM    
    MEMBERS m 
    INNER JOIN CHKINS c 
    ON m.memid = c.memid 
    AND c.ischeckin = 'TRUE' 
    --AND c.checkin BETWEEN @rvStartDate AND DATEADD(day, 45, @rvStartDate) --only include if you want to also limit the checkins by the same date range 
WHERE 
    m.relationship = 'M' 
    AND m.status = 'A' --if you want all statuses comment this line by adding -- in front 
    AND m.mtypeid IN ('1','10','12','22','28','32','33','34','35','36','40','48') 
    --AND m.mtypeid IN (1,10,12,22,28,32,33,34,35,36,40,48) --uncomment and use this line instead of above if m.mtypeid is a numeric data type (int, smallint, tinyint, etc.) 
    AND m.datejoin BETWEEN @rvStartDate AND @rvEndDate 
GROUP BY 
    m.fname 
    ,m.lname 
    ,m.description 
    ,m.phone1 
    ,m.phone2 
    ,m.lastvisit 
    ,m.email 
    ,m.datejoin 
    ,m.dateexpire 
    ,m.daterenewal 
    ,m.relationship 
    ,m.mtypeid 
    ,m.status 
ORDER BY 
    m.fname 
    ,m.lastname 
    --this sorts list by First name then Last Name switch order if you want last first 
    --or you can simply put CountOfCheckins to order by the least to greatest checkins or CountOfCheckins to get the greatest to the least 
関連する問題