[英]How do I use T-SQL's Exists keyword?
我有一個查詢要作為子查詢運行,該查詢將返回一組FK。 對於它們,我只想返回具有匹配鍵的行。
SELECT ID
FROM tblTenantTransCode
WHERE
tblTenantTransCode.CheckbookCode =
(SELECT ID FROM tblCheckbookCode WHERE Description = 'Rent Income')
這將返回所有具有與租金收入匹配的支票簿代碼的交易代碼
現在,我要選擇所有事務的事務代碼與子查詢中返回的ID匹配的所有事務。 到目前為止,我已經了解了,但是SQL Server抱怨語法錯誤。 我怎樣才能做到這一點?
SELECT *
FROM tblTransaction
WHERE
tblTransaction.TransactionCode IN
(SELECT ID FROM tblTenantTransCode
WHERE tblTenantTransCode.CheckbookCode =
(SELECT ID FROM tblCheckbookCode WHERE Description = 'Rent Income'))
tblCheckbookCode ID Description Other Info tblTenantTransCode ID CheckbookCode <-- fk we're looking for in the tblCheckbookCode. We're selecting only checkbook codes that have the Description 'Rent Income' Other Info tblTransactions ID TransactionCode <-- fk to tenant transaction code. We're looking for an ID that is returned in the above query/join
為了回答有關使用EXISTS關鍵字的問題,下面是一個示例查詢,該查詢基於您問題中當前給出的查詢,使用EXISTS謂詞。
SELECT t.* FROM tblTransaction t WHERE EXISTS ( SELECT 1 FROM tblTenantTransCode ttc JOIN tblCheckbookCode cc ON (cc.ID = ttc.CheckbookCode AND cc.Description='Rent Income') WHERE ttc.ID = t.TransactionCode )
額外細節:
我們都知道,有各種各樣的SQL語句將返回滿足指定要求的結果集。 這些查詢的觀察性能可能會有所不同。 性能尤其取決於DBMS,優化器模式,查詢計划和統計信息(行數和數據值分布)。
EXISTS
優點之一在於,很明顯,我們對從子查詢表中返回任何表達式都不感興趣。 它用於以邏輯上的方式將子查詢與外部查詢分開,而JOIN
則沒有。
使用EXISTS
另一個優點是避免了返回重復的行,如果我們改為使用JOIN
,這些行將(可能)返回。
EXISTS
謂詞可用於測試子表中是否存在任何相關行,而無需聯接。 例如,以下查詢返回一組至少具有一個關聯的line_item的所有訂單:
SELECT o.* FROM order o WHERE EXISTS ( SELECT 1 FROM line_item li WHERE li.order_id = o.id )
請注意,子查詢不需要查找所有匹配的訂單項,只需要查找一行即可滿足條件。 (如果我們將此查詢編寫為JOIN
,則每當訂單中有一個以上訂單項時,我們都會返回重復的行。)
NOT EXISTS
謂詞也很有用,例如,返回沒有任何關聯的line_items的一組訂單。
SELECT o.* FROM order o WHERE NOT EXISTS ( SELECT 1 FROM line_item li WHERE li.order_id = o.id )
當然, NOT EXISTS
只是一種選擇。 可以使用OUTER連接和IS NULL測試獲得等效的結果集(假設我們從line_item表中至少有一個不是NOT NULL的表達式)
SELECT o.* FROM order o LEFT JOIN line_item li ON (li.order_id = o.id) WHERE li.id IS NULL
關於需要使用IN
謂詞或需要使用JOIN
似乎有很多討論(與原始問題的答案有關)。
這些構造是替代的,但不是必需的。 查詢可以返回所需的結果集,而無需使用IN
和JOIN
。 可以通過使用EXISTS
謂詞的查詢返回結果集。 (請注意,OP問題的標題確實詢問了如何使用EXISTS
關鍵字。)
這是另一個替代查詢(這不是我的首選),但是返回的結果集確實滿足指定的要求:
SELECT t.* FROM tblTransaction t WHERE EXISTS ( SELECT 1 FROM tblTenantTransCode ttc WHERE ttc.ID = t.TransactionCode AND EXISTS ( SELECT 1 FROM tblCheckbookCode cc WHERE cc.ID = ttc.CheckbookCode AND cc.Description = 'Rent Income' ) )
最重要的是,查詢應返回正確的結果集,該結果集應滿足所有可能的條件集,並滿足指定的要求。
此處以答案形式出現的某些查詢不會返回請求的結果集,或者如果返回的話,它們恰巧是偶然返回的。 如果我們預先假設一些有關數據的查詢,則某些查詢將起作用,例如,某些UNIQUE
和NOT NULL
。
性能差異
有時,帶有EXISTS
謂詞的查詢的性能不如帶有JOIN
或IN
謂詞的查詢。 在某些情況下,它的性能可能更好。 (使用EXISTS
謂詞,子查詢只需要查找滿足條件的一行,而不必查找JOIN
所需的所有匹配行。)
各種查詢選項的性能最好通過觀察來衡量。
您正在描述內部聯接。
select tc.id
from tblTenantTransCode tc
inner join tblCheckbookCode cc on tc.CheckbookCode = cc.CheckbookCode
編輯:這仍然是一個內部聯接。 我看不出有任何理由要使用IN子句。
select *
from tblTransaction t
inner join tblTenantTransCode tc on tc.id = t.TransactionCode
inner join tblCheckbookCode cc on cc.id = tc.CheckbookCode
where cc.description = 'Rent Income'
編輯:如果必須使用EXISTS謂詞來解決此問題,請參見@ spencer7953的答案。 但是,據我所知,上面的解決方案比較簡單,並且基於“子查詢”為您工作這一事實(因此如果該表中沒有唯一性,則不會100%的時間),就存在唯一性假設)。 我也在講
現在,我要選擇所有事務的事務代碼與子查詢中返回的ID 匹配的所有事務
在我的回答中。 如果請求是這樣的話:
現在, 當任何交易代碼與子查詢中返回的ID匹配時,我想選擇“所有交易”。
我將使用EXISTS來查看子表中是否存在任何交易代碼,並酌情返回每一行或不返回任何行。
給定您的完整查詢,此查詢將使您可以使用單個聯接到達所需的位置。
聯接會過濾出沒有“ Rent Income”交易代碼的任何交易。 它將從第一個表中獲取所有記錄,構建第二個表的子集(該WHERE子句限制了這些記錄),然后過濾第一個表,其中那些表對聯接條件進行數學運算。
SELECT
t.*
FROM
tblTransaction t
INNER JOIN tblTenantTransCode c ON
t.TransactionCode = c.ID
INNER JOIN tblCheckbookCode chk ON
c.CheckbookCode = chk.ID
WHERE
chk.Description = 'Rent Income'
編輯:另一個注意事項:避免使用SELECT *-始終指定列。 編輯注意事項:我錯過了三張桌子。 更正! 謝謝,斯潘塞!
嘗試這個:
SELECT
tblTenantTransCode.ID
FROM tblCheckbookCode
INNER JOIN tblTenantTransCode ON tblCheckbookCode.ID=tblTenantTransCode.CheckbookCode
WHERE tblCheckbookCode.Description = 'Rent Income'
確保您索引tblCheckbookCode.Description
。
您需要使用“ IN”子句:
select id from tblTenantTransCode
where tblTenantTransCode.CheckbookCode in
(select id from tblCheckbookCode
where description = 'rent income')
內部連接可能是更好的解決方案...
select ttc.id from tblTenantTransCode as ttc
inner join tblCheckbookCode as tcc
on ttc.CheckBookId = tcc.id
where tcc.description = 'rent income'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.