2009-09-12 50 views
1

有人能想出如何擺脫WHERE子句中的NOT EXISTS語句嗎?自加入而不是子查詢

SELECT TOP 100 PERCENT 
    Ftm.AcctID AS [Acct Id], 
    Act.AccountNumber AS [Account No.], 
    Act.AccountTypeId, 
    ISNULL(Cnt.FirstName, '')+ ' ' + ISNULL(Cnt.LastName, '') AS [Full Name], 
    Ftm.FinTransTypeCode AS [Trans Type], 
    Ftm.FinTransCode AS [Trans Code], 
    Fm.FJNo AS [FJ No.], 
    Fm.ReversalFJNo AS [Reversal FJNo.], 
    CAST(ISNULL(Fm.FJAmt,0) AS DECIMAL(9, 2)) AS Amount, 
    Ftc.InterfaceDescr AS [Transaction Desc], 
    Fm.Comments, Fm.CreatedBy AS [Posted By], 
    Ftm.Created,RegistrationTypeid, FJDate 
FROM 
    FinMaster AS Fm 
    INNER JOIN FinTransMaster AS Ftm ON Ftm.FjNo = Fm.FJNo 
    INNER JOIN dbo.Account AS Act ON Ftm.AcctID = Act.AccountId 
    INNER JOIN dbo.Contact AS Cnt ON Act.PrimaryContactId = Cnt.ContactId 
    INNER JOIN FinTransCodes AS Ftc ON Ftc.FinTransCode = Ftm.FinTransCode 
WHERE  
    (Ftm.FinTransTypeCode <> 'PYMT') AND FJDate > getdate()-5 
    AND (NOT EXISTS (SELECT '' AS Expr1 
        FROM FinMaster 
        WHERE (ReversalFjNo = Fm.FJNo))) 
    AND (NOT EXISTS (SELECT '' AS Expr1 
        FROM FinTransMaster AS Ftm2 
        WHERE (FjNo = Ftm.FjNo) AND (FjTransSeqNo < Ftm.FjTransSeqNo))) 
ORDER BY Ftm.Created DESC 
+0

我想提早找出同樣的事情今天 – 2009-09-12 00:09:38

+1

在SQL Server中,NOT IN/NOT EXISTS都優於LEFT JOIN,因爲它的優化器無法辨別反中加入LEFT JOIN/IS NULL 。它將返回整個結果集,然後過濾出NULL。 – 2009-09-12 00:41:47

回答

4

在SQL Server中,NOT IN/NOT EXISTS 更好比LEFT JOIN,因爲它的優化器無法辨別反在LEFT JOIN JOIN/IS NULL。它將返回整個結果集,然後過濾出NULL。

WITH contacts AS (
    SELECT t.contactid, 
      CASE 
       WHEN t.firstname IS NULL AND t.lastname IS NULL THEN 
       '' 
       WHEN t.firstname IS NULL THEN 
       t.lastname 
       WHEN t.lastname IS NULL THEN 
       t.firstname 
       ELSE 
       t.FirstName + ' ' t.LastName 
      END AS [fullname] 
     FROM dbo.CONTACT t) 
SELECT TOP 100 PERCENT 
     ftm.AcctID AS [Acct Id], 
     a.AccountNumber AS [Account No.], 
     a.AccountTypeId, 
     c.fullname AS [Full Name], 
     ftm.FinTransTypeCode AS [Trans Type], 
     ftm.FinTransCode AS [Trans Code], 
     t.FJNo AS [FJ No.], 
     t.ReversalFJNo AS [Reversal FJNo.], 
     CAST(ISNULL(t.FJAmt, 0) AS DECIMAL(9, 2)) AS Amount, 
     ftc.InterfaceDescr AS [Transaction Desc], 
     t.Comments, 
     t.CreatedBy AS [Posted By], 
     ftm.Created, 
     RegistrationTypeid, 
     FJDate 
FROM FINMASTER t 
JOIN FINTRANSMASTER ftm ON ftm.FjNo = t.FJNo 
         AND ftm.FinTransTypeCode <> 'PYMT' 
JOIN dbo.ACCOUNT a ON a.accountid = ftm.AcctID 
JOIN contacts c ON c.contactid = a.PrimaryContactId 
JOIN FINTRANSCODES ftc ON ftc.FinTransCode = ftm.FinTransCode 
WHERE FJDate > getdate()-5 
    AND NOT EXISTS (SELECT NULL 
        FROM FinMaster fm 
        WHERE fm.ReversalFjNo = t.FJNo) 
    AND NOT EXISTS (SELECT NULL 
        FROM FinTransMaster AS ftm2 
        WHERE ftm2.FjNo = ftm.FjNo 
        AND ftm2.FjTransSeqNo < ftm.FjTransSeqNo) 
ORDER BY ftm.Created DESC 
0

我覺得你可以做OUTER對FinMaster和FinTransMaster表的連接,並具有where子句指定與表的ID是空的。

0

你只需要做連接,其中爲空。
下面是使用時所提供的查詢的示例:

SELECT TOP 100 PERCENT
Ftm.AcctID AS [科目ID],
Act.AccountNumber AS [帳戶編號],
Act.AccountTypeId,
ISNULL(Cnt.FirstName, '')+ '' + ISNULL(Cnt.LastName, '')AS [姓名],
Ftm.FinTransTypeCode AS [反式],
Ftm.FinTransCode AS [反代碼] ,
Fm.FJNo AS [FJ No.],
Fm .ReversalFJNo AS [逆轉FJNo。],
CAST(ISNULL(Fm.FJAmt,0)爲十進制(9,2))AS金額,
Ftc.InterfaceDescr AS [事務DESC],
Fm.Comments,FM .CreatedBy AS [發佈者],
Ftm.Created,RegistrationTypeid,FJDate

FROM FinMaster AS FM
INNER JOIN FinTransMaster AS FTM ON Ftm.FjNo = Fm.FJNo
INNER JOIN dbo.Account AS作用於Ftm.AcctID = Act.AccountId
INNER JOIN dbo.Contact AS Cnt ON Act.PrimaryContactId = Cnt.ContactId
INNER JOIN FinTransCodes AS FTC ON Ftc.FinTransCode = Ftm.FinTransCode

left outer join FinMaster as FM2 on FM2.ReversalFjNo = Fm.FJNo and FM2.ReversalFjNo is null 
left outer join FinTransMaster AS Ftm2 on (Ftm2.FjNo = Ftm.FjNo) AND (Ftm2.FjTransSeqNo < Ftm.FjTransSeqNo) 
      and Ftm2.FjNo is null 

WHERE
(Ftm.FinTransTypeCode <> 'PYMT')AND FJDate> GETDATE() - 5

ORDER BY FTM .Created DESC

2

爲什麼你想讓自己接受?很好地使用子查詢(特別是使用IN和NOT IN)使得查詢更具可讀性,並且在大多數數據庫引擎中它們也同樣快速。

通常,在要從中進行選擇的表上使用JOIN和對其他所有項進行子查詢會得到最清晰的查詢。這是我的建議。

SELECT TOP 100 PERCENT 
    Ftm.AcctID AS [Acct Id], 
    Act.AccountNumber AS [Account No.], 
    Act.AccountTypeId, 
    ISNULL(Cnt.FirstName, '')+ ' ' + ISNULL(Cnt.LastName, '') AS [Full Name], 
    Ftm.FinTransTypeCode AS [Trans Type], 
    Ftm.FinTransCode AS [Trans Code], 
    Fm.FJNo AS [FJ No.], 
    Fm.ReversalFJNo AS [Reversal FJNo.], 
    CAST(ISNULL(Fm.FJAmt,0) AS DECIMAL(9, 2)) AS Amount, 
    Ftc.InterfaceDescr AS [Transaction Desc], 
    Fm.Comments, Fm.CreatedBy AS [Posted By], 
    Ftm.Created,RegistrationTypeid, FJDate 
FROM 
    FinMaster AS Fm 
    INNER JOIN FinTransMaster AS Ftm ON Ftm.FjNo = Fm.FJNo 
    INNER JOIN dbo.Account AS Act ON Ftm.AcctID = Act.AccountId 
    INNER JOIN dbo.Contact AS Cnt ON Act.PrimaryContactId = Cnt.ContactId 
    INNER JOIN FinTransCodes AS Ftc ON Ftc.FinTransCode = Ftm.FinTransCode 
WHERE  
    (Ftm.FinTransTypeCode <> 'PYMT') AND FJDate > getdate()-5 
    AND Fm.FJNo NOT IN (
        SELECT ReversalFjNo 
        FROM FinMaster 
        WHERE ReversalFjNo IS NOT NULL) 
    AND Ftm.FjNo NOT IN (
        SELECT FjNo 
        FROM FinTransMaster AS Ftm2 
        WHERE FjNo IS NOT NULL) 
    AND (FjTransSeqNo < Ftm.FjTransSeqNo))) 
ORDER BY Ftm.Created DESC 
+0

+1支持代碼可讀性。 SQL不是最簡單的語言來讀取和解釋。但請注意:代碼可讀性與代碼性能直接平衡並不罕見。它們本身不成反比,但必須小心謹慎地記錄更難以讀懂的代碼部分。 OP可能一直在尋找更容易維護的查詢或更高性能的查詢。 – 2009-09-12 01:48:12