1

新しい条件が発生し、それが私を混乱させるまで、私はこのクエリのほとんどを停止しました。次の簡略化されたテーブルスキーマがあるとします。

親テーブル:

ID  
FName  
LName 

子テーブル:

[Index]  
ParentID  
Active_Flag  
ExpirationDate 

私がやりたいのは、次のような親行を取得することです。

  1. 子供はいません。
  2. Active_Flagが1であるが、有効期限が空白またはNULLである子があります。
  3. 確かに子はありますが、Active_Flagが1に設定されている子はありません。

次のクエリは私の最初の2つの基準を思いついた:

SELECT p.ID, p.LNAME, p.FNAME,
    CASE 
        WHEN COUNT(ct.indx) = 0 THEN 'None'
        WHEN ct.ExpirationDate is NULL or ct.ExpirationDate = '' THEN 'No expiration date'
    END AS Issue
FROM ParentTable AS p 
    LEFT JOIN ChildTable ct
        ON p.ID = ct.ParentID
GROUP BY p.ID, p.LNAME, p.FNAME, ct.[INDEX], ct.ExpirationDate
HAVING (COUNT(ct.[INDEX]) = 0) OR (ct.ExpirationDate IS NULL OR ct.ExpirationDate = '')
ORDER BY p.LNAME

#3の説明方法がわかりません。どんな助けでも大歓迎です。前もって感謝します。

4

3 に答える 3

2

HAVING句でこれを行うこともできます。

SELECT p.ID, p.LNAME, p.FNAME,
       (CASE WHEN COUNT(ct.indx) = 0 THEN 'None'
             WHEN ct.ExpirationDate is NULL or ct.ExpirationDate = '' THEN 'No expiration date'
             WHEN sum(case when ActiveFlag = 1 then 1 else 0 end) = 0 then 'No active children'
        END) AS Issue
FROM ParentTable p LEFT JOIN
     ChildTable c
    ON p.ID = ct.ParentID
GROUP BY p.ID, p.LNAME, p.FNAME
HAVING (COUNT(ct.[INDEX]) = 0) OR
       (ct.ExpirationDate IS NULL OR ct.ExpirationDate = '') or
       sum(case when ActiveFlag = 1 then 1 else 0 end) = 0
ORDER BY p.LNAME

SELECTのDISTINCTは冗長です。アグリゲーションでは必要ありません。

activeFlagが実際に整数である場合は、「sum(ActiveFlag)」の必要性を単純化できます。そうでない場合は、「=1」ではなく「=1」にする必要があります。

于 2012-09-14T20:50:34.050 に答える
0
SELECT  * 
FROM parenttable pt
        -- condition 1: There should be no parents without children at all
WHERE NOT EXISTS (
        SELECT * FROM childtable c1
        WHERE c1.parent_id = pt.id
        )
        -- condition 2: There should be no children with a flag but without a date
OR EXISTS (
        SELECT * FROM childtable c2
        WHERE c2.parent_id = pt.id
        AND c2.active_flag = 1 AND c2.expire_date IS NULL
        )
        -- condition 3: There should at least be a child with the active_flag
OR NOT EXISTS (
        SELECT * FROM childtable c3
        WHERE c3.parent_id = pt.id
        AND c2.active_flag = 1 
        )
        ;

-- Active flags for children c1 and c2
-- c1   c2 (X= child doesn't exists)
-----+-----+---+
-- X    X       rule1+rule3     # no children at all
-- 0    X       rule3           # only one child
-- 1    X                       # idem
-- 0    0       rule 3          # two children
-- 0    1
-- 1    0
-- 1    1
--
-- , which means that rule3 implies rule1, and rule1 is redundant
-------------------------

SELECT  * 
FROM parenttable pt
        -- condition 1+3: There should at least be a child with the active_flag
WHERE NOT EXISTS (
        SELECT * FROM childtable c1
        WHERE c1.parent_id = pt.id
        AND c1.active_flag = 1
        )
        -- condition 2: There should be no children with a flag but without a date
OR EXISTS (
        SELECT * FROM childtable c2
        WHERE c2.parent_id = pt.id
        AND c2.active_flag = 1 AND c2.expire_date IS NULL
        )
        ;
于 2012-09-15T13:51:44.370 に答える
0

このクエリにユニオンを使用できます.....このクエリについてはわかりません....しかし、問題の解決に役立ちます

 select p.id,p.lname,p.fname from parents where (p.id not in (select pid from children))
    union  
    select p.id,p.lname,p.fname from parents p,children c inner join on c.pid=p.id where c.active_flag=1 and c.expiration_date is null or c.expiration_date=''
    union
    select p.id,p.lname,p.fname from parents p inner join on c.pid=p.id where c.active_flag<>1;
于 2012-09-14T21:04:32.797 に答える