选择具有多个条件的父行

时间:2012-09-14 20:45:08

标签: sql

我把这个问题的大部分都放下了,直到新的情况出现并且让我感到困惑。给出以下简化表模式:

父表:

ID  
FName  
LName 

子表:

[Index]  
ParentID  
Active_Flag  
ExpirationDate 

我想要做的是获取父行:

  1. 没有孩子。
  2. 有些子级的Active_Flag为1,但其到期日期为空或NULL。
  3. 确实存在子项,但没有将Active_Flag设置为1.
  4. 我的前两个标准提出了以下查询:

    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。任何帮助表示赞赏。提前谢谢。

3 个答案:

答案 0 :(得分: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”。

答案 1 :(得分: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;

答案 2 :(得分: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
        )
        ;