2009-09-12 52 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