[英]SQL join where all joined meet condition
我需要一些有關SQL查詢的幫助。
我有桌子:客戶| 索賠| 狀態| 往來
我有一個查詢來查找所有客戶及其聯系方式,其中任何索償均為指定狀態:
SELECT
clients.id AS "Client Ref"
,claims.clientclaimid AS "Claim Number"
,Contacts.PhoneHome AS "Mobile"
,statuses.description AS Status
FROM
dbo.claims
LEFT JOIN
statuses
ON
dbo.claims.statusID = statuses.ID
LEFT JOIN
clients
ON
dbo.claims.clientid = clients.id
LEFT JOIN
contacts
ON
clients.contactid = Contacts.id
WHERE
statuses.description = 'client - pack sent to customer'
AND (DATEADD(MM, -@joinedpremonthsago, GETDATE()) > clients.DateJoined)
AND clients.DateJoined > 01 / 01 / 2012
AND claims.active = 1
ORDER BY
[Client Ref]
,[Claim Number];
現在,我只需要將所有聲明都處於指定狀態的客戶拉出,但是我不知道該怎么做。 如何獲得所有聲明都具有此狀態描述的客戶? 我可以為此提供指導或解決方案嗎?
這是相關的架構; 索償表
這是查詢返回的圖像,其中客戶的任何索賠都處於狀態。 當前結果
解決的辦法是使用排除原則。 您編寫查詢以獲取所有確實具有該狀態的所有客戶端至少一次。 好消息:這部分已經完成了:)接下來,編寫查詢以查找具有其他任何狀態的客戶端。 擁有兩個查詢后,將它們組合在一起即可從第一組中排除第二組。 您可以通過幾種方式執行此操作: NOT EXISTS()
表達式, NOT IN()
表達式,排除EXCEPT
或EXCEPT
關鍵字都可以起作用。
就個人而言,我對排除連接最為滿意,但NOT EXISTS()
更為常見,並且往往表現得更好:
select cli.id as "Client Ref", cla.clientclaimid as "Claim Number", co.PhoneHome as "Mobile"
from dbo.claims cla
inner join statuses s on cla.statusID = s.ID
inner join clients cli on cla.clientid = cli.id
left join contacts co on cli.contactid = co.id
where s.description = 'client - pack sent to customer'
and (DateAdd(MM, -@joinedpremonthsago, GetDate()) > cli.DateJoined)
and cli.DateJoined > 01/01/2012
and cla.active=1
and NOT EXISTS (
select 1
from clients cli0
inner join claims cla0 on cla0.clientid = cli0.id
inner join statuses s0 on s0.ID = cla0.statusID
WHERE cli0.ID = cli.ID
AND s0.description <> 'client - pack sent to customer'
)
order by [Client Ref], [Claim Number]
排除聯接版本:
select cli.id as "Client Ref", cla.clientclaimid as "Claim Number", co.PhoneHome as "Mobile"
from dbo.claims cla
inner join statuses s on cla.statusID = s.ID AND s.description = 'client - pack sent to customer'
inner join clients cli on cla.clientid = cli.id
left join contacts co on cli.contactid = co.id
-- the "JOIN" part of an exclusion join
left join statuses s2 on cla.statusID = s2.ID AND s2.description <> 'client - pack sent to customer'
where (DateAdd(MM, -@joinedpremonthsago, GetDate()) > cli.DateJoined)
and cli.DateJoined > 01/01/2012
and cla.active=1
-- the "EXCLUSION" part of an exclusion join
and s2.ID IS NULL
order by [Client Ref], [Claim Number]
請注意,我是如何選擇“ inner
而不是“ left
來進行某些原始連接的。 在WHERE子句中使用這些表的字段的方式已經使它們有效地成為內部聯接。 對聯接類型誠實可以幫助您發現錯誤,並可以使Sql Server建立更好的執行計划。
還要注意,我從SELECT子句結果中刪除了狀態,因為現在要求已隱含了這一點。
最后,請注意如何將表別名添加到查詢中。 最好在查詢中始終使用表別名。 如果您想在單個查詢中多次引用同一張表,則絕對有必要避免歧義,就像我們在此處的兩個示例中一樣。 按照慣例,這些別名通常是表名的縮寫,甚至是單個字母。 因此,此查詢中的cli
是client
縮寫,我使用了3個完整字符,以便將其與claims
區分開。 內部查詢中使用cli0
表示“客戶素數” ...認為0
就像是下標。
類似於(完全未經測試的代碼!):
select clients.id as "Client Ref", claims.clientclaimid as "Claim Number",
Contacts.PhoneHome as "Mobile",statuses.description as Status
from dbo.claims
left join clients on dbo.claims.clientid = clients.id
left join contacts on clients.contactid = contacts.id
where (DateAdd(MM, -@joinedpremonthsago, GetDate()) > clients.DateJoined)
and clients.DateJoined > 01/01/2012
and claims.active=1
and dbo.claims.clientID in (
select dbo.claims.clientID
from dbo.claims
left join statuses on dbo.claims.statusID = statuses.ID
where statuses.description = 'client - pack sent to customer'
)
order by [Client Ref], [Claim Number]
應該做到的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.