2017-06-15 111 views
1

我正在SQL Server 2008數據庫上運行2個報表。父表是帳戶,子表是合同,並且它們在唯一標識符字段 - 帳戶ID上鍊接。SQL添加額外的子查詢以排除主要查詢的結果

我的目標是根據什麼類型的合同提供所有賬戶和合同。

我有這個疑問現在:

Select Account.*, C.* from Account 

Left Join Contracts C 
on C.AccountID=Account.AccountId 

Where 

(Case when C.T1 = 'TYPE1' or C.T1 = 'TYPE2' or C.T1 = 'TYPE3' or C.T1 = 'TYPE4' or C.T1 = 'TYPE5' or C.T1 = 'TYPE6' Then 0 Else 1 END) = 0 
and EXISTS (Select E.AccountID, E.T1 from Contracts E Where E.AccountID = C.AccountID and (E.T1 LIKE 'TYPE6' and Convert(Date,E.End_Date) = Convert(Date,C.End_Date))) 

Order by Account.AccountID 

的想法是拉有合同的所有帳戶,其中T1 = TYPE1-6,但前提是他們有合同在哪裏T1 = TYPE6。這給出的結果是這樣的:

AccountID Contract T1 
    1    1  4 
    1    2  5 
    1    3  6 

    2    4  6 
    2    5  2 
    2    6  6 

    3    7  6 
    3    8  6 
    3    9  6 

我從這個需要接下來的事情是,它排除只有合同TYPE6帳戶,我完全失去了。理想的結果是,我將獲得帳戶1 & 2的所有3份合同,但會從結果中刪除帳戶3。

我的假設是,我將需要一個額外的查詢,給我我不想要的結果。我不完全理解EXCEPT語句,但我覺得可能需要放在這裏嗎?

該查詢給了我所有的帳戶/合同不應該包括在我的第一個結果:

Select Account.*, C.* from Account 

Left Join Contracts C 
on C.AccountID=Account.AccountId 

where 
(Case When C.T1 = 'TYPE6' Then 0 Else 1 End) = 0 
and NOT EXISTS (Select E.AccountID, E.T1 from Contracts E Where E.AccountID = C.AccountID and E.T1 NOT LIKE '%TYPE6%'and Convert(Date,E.End_Date) = Convert(Date,C.End_Date)) 


Order by Account.AccountID 

有沒有辦法對我說「從第一查詢給我的一切,但排除一切從第二?'

此外任何清理我的言論的意見,將不勝感激。我並不是自稱擅長這一點。

謝謝!

+1

喜並歡迎來到SO。我們需要一些細節以幫助更多。這裏是一個開始的好地方。 http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

+0

我不明白爲什麼帳戶2在您的結果中。它不符合你的標準,「但只有當他們有一個合同在哪裏T1 = TYPE6」。帳戶2只有類型1,2和3.沒有類型6. –

+0

@SeanLange這是我可以給的所有信息。我無法給你任何樣本數據。 – Brennen

回答

0

最後一個條件應該做的伎倆與另一合同的存在的測試,是不是6類的(我沒有在本地測試)

Select Account.*, C.* from Account 

     Left Join Contracts C 
     on C.AccountID=Account.AccountId 

     Where 

     (Case when C.T1 = 'TYPE1' or C.T1 = 'TYPE2' or C.T1 = 'TYPE3' or C.T1 = 'TYPE4' or C.T1 = 'TYPE5' or C.T1 = 'TYPE6' Then 0 Else 1 END) = 0 
     and EXISTS (Select E.AccountID, E.T1 from Contracts E Where E.AccountID = C.AccountID and (E.T1 LIKE 'TYPE6' and Convert(Date,E.End_Date) = Convert(Date,C.End_Date))) 
    AND (C.T1 <> 'TYPE6' OR EXISTS(SELECT * FROM Contracts con WHERE con.AccountId = Account.AccountId AND con.T1 <> 'TYPE6')) 

     Order by Account.AccountID 
+0

感謝您的回答。不幸的是,這不適用於有一份TYPE6合同的帳戶,但它確實讓我更接近! – Brennen

0

你想上的帳戶信息(無論是任何或所有它的記錄是類型6)。所以按帳戶ID進行分組並檢查您的帳戶。

select accountid 
from contracts 
where t1 between 1 and 6 
group by accountid 
having count(case when t1 = 6 then 1 end) > 0 -- at least one record of type 6 
    and count(case when t1 <> 6 then 1 end) > 0 -- at least one record of type 1 to 5 

然後,您可以選擇這些帳戶的記錄:

select * 
from accounts a 
join contracts c on c.accountid = a.accountid 
where c.t1 between 1 and 6 and c.accountid in (<above query>); 

,你讀表一次使用,而不是COUNT解析函數COUNT OVER一種替代方案:

select accountid, contract, t1 
from 
(
    select 
    a.*, c.*, 
    count(case when c.t1 = 6 then 1 end) over (partition by c.accountid) as c6, 
    count(case when c.t1 <> 6 then 1 end) over (partition by c.accountid) as c12345 
    from accounts a 
    join contracts c on c.accountid = a.accountid 
    where c.t1 between 1 and 6 
) mydata 
where c6 > 0 and c12345 > 0; 
+0

在你的例子中,你選擇的所有列都存在於'contracts'中。如果您確實不想從'accounts'獲得更多數據,請從上述查詢中移除該表。 –