2012-09-14 24 views
1

我有這個查詢的大部分,直到一個新的條件出現,它讓我困惑。鑑於以下簡化表模式:選擇具有多個條件的父行

父表:

ID 
FName 
LName 

子表:

[Index] 
ParentID 
Active_Flag 
ExpirationDate 

我想要做的就是針對父行:

  1. 有沒有孩子。
  2. 有些孩子的Active_Flag爲1,但其有效日期爲空或NULL。
  3. 的確是有孩子但沒有了Active_Flag設置爲1

下面的查詢提出了我的前兩個標準:

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。任何幫助表示讚賞。提前致謝。

+0

1.能不能請你澄清#2?尤其是,這將是正確的假設,如果有與'Active_Flag = 1'任何子女,*所有*它們的過期日期都必須爲空或NULL以滿足條件?2.什麼是「ct」別名,以及爲什麼「ct」的列既不會聚合也不會包含在您的查詢中的GROUP BY中在SELECT和HAVING中)? –

+0

當您使用Group By時,您不需要添加Distinct – Beth

+0

這些是在將我的REAL查詢轉換爲此虛擬版本時發生的問題。我做了適當的修改。 – DerPflug

回答

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 

的DISTINCT的SELECT是多餘的。你不需要聚合。

如果activeFlag確實是一個整數,則可以簡化不得不使用「sum(ActiveFlag)」。如果不是,那麼它應該是「='1'」而不是「= 1」。

0

您可以使用此聯合查詢..... 我不確定這個查詢....但它將幫助您解決prolem

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; 
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 
     ) 
     ;