内部联接时缺少特定人员的sql跟踪记录

内部联接时缺少特定人员的sql跟踪记录,sql,sql-server,Sql,Sql Server,我有一个这样的问题,但我想知道是否有更好的方法,而不是下面的尝试 列出信用余额少于50个且在2018年未进行任何交易的所有会员的信用余额 SELECT m.CreditBalance FROM Member m INNER JOIN CreditCard cc ON m.MemberID=cc.MemberID INNER JOIN CreditDebitTrans cdt ON cc.CardNo=cdt.CardNo WHERE (cdt.TransDateTime != DATEPAR

我有一个这样的问题,但我想知道是否有更好的方法,而不是下面的尝试

列出信用余额少于50个且在2018年未进行任何交易的所有会员的信用余额

SELECT m.CreditBalance
FROM Member m 
INNER JOIN CreditCard cc
ON m.MemberID=cc.MemberID
INNER JOIN CreditDebitTrans cdt
ON cc.CardNo=cdt.CardNo
WHERE (cdt.TransDateTime  != DATEPART(Year,2018) 
AND
m.CreditBalance<50)

这仅对范围内的事务进行筛选,然后cdt.CardNo为空,因为这是连接条件,表示该范围内的cdt记录上有个

SELECT m.memberid, m.CreditBalance
FROM Member m 
INNER JOIN CreditCard cc
ON m.MemberID=cc.MemberID
LEFT OUTER JOIN CreditDebitTrans cdt
ON cc.CardNo=cdt.CardNo and cdt.TransDateTime>='2018-01-01' and cdt.TransDateTime<'2019-01-01'
WHERE cdt.CardNo Is Null and m.CreditBalance<50
group by m.memberid, m.CreditBalance

这仅对范围内的事务进行筛选,然后cdt.CardNo为空,因为这是连接条件,表示该范围内的cdt记录上有个

SELECT m.memberid, m.CreditBalance
FROM Member m 
INNER JOIN CreditCard cc
ON m.MemberID=cc.MemberID
LEFT OUTER JOIN CreditDebitTrans cdt
ON cc.CardNo=cdt.CardNo and cdt.TransDateTime>='2018-01-01' and cdt.TransDateTime<'2019-01-01'
WHERE cdt.CardNo Is Null and m.CreditBalance<50
group by m.memberid, m.CreditBalance

您还可以在where子句中创建一个子查询。但这与您已经做的几乎相同:

SELECT 
    m.CreditBalance
FROM 
    Member m 
WHERE   
    m.CreditBalance<50
    AND m.MemberID NOT IN (
        SELECT 
            cc.MemberID
        FROM
            CreditCard cc
        INNER JOIN      
            CreditDebitTrans cdt
        WHERE   
            cdt.TransDateTime = DATEPART(Year,2018) 
    )

您还可以在where子句中创建一个子查询。但这与您已经做的几乎相同:

SELECT 
    m.CreditBalance
FROM 
    Member m 
WHERE   
    m.CreditBalance<50
    AND m.MemberID NOT IN (
        SELECT 
            cc.MemberID
        FROM
            CreditCard cc
        INNER JOIN      
            CreditDebitTrans cdt
        WHERE   
            cdt.TransDateTime = DATEPART(Year,2018) 
    )
我喜欢在这种情况下使用存在

SELECT m.CreditBalance
FROM Member m
WHERE
    m.CreditBalance < 50
    -- There are no transactions for the member in 2018:
    AND NOT EXISTS (
        SELECT 1
        FROM CreditCard cc
            INNER JOIN CreditDebitTrans cdt ON cdt.CardNo = cc.CardNo
        WHERE cc.MemberID = m.MemberID
            AND cdt.TransDateTime >= '2018-01-01'
            AND cdt.TransDateTime < '2019-01-01'
    );
我喜欢在这种情况下使用存在

SELECT m.CreditBalance
FROM Member m
WHERE
    m.CreditBalance < 50
    -- There are no transactions for the member in 2018:
    AND NOT EXISTS (
        SELECT 1
        FROM CreditCard cc
            INNER JOIN CreditDebitTrans cdt ON cdt.CardNo = cc.CardNo
        WHERE cc.MemberID = m.MemberID
            AND cdt.TransDateTime >= '2018-01-01'
            AND cdt.TransDateTime < '2019-01-01'
    );

您好,您能解释更多关于cdt.CardNo为空吗?那么,由于它是一个左外连接,连接的内容没有记录…这些表中的所有字段都将返回空值…因为卡号是一个可以安全假设的非空字段…所以检查它为空意味着我们没有creditdebittrans记录。您能解释更多关于cdt.CardNo为空吗?那么,因为它是一个左外连接,连接的内容没有记录…这些表中的所有字段都将返回空字段…因为卡号是一个非空字段,可以安全地假设…所以检查它是否为空意味着我们没有creditdebittrans recordshi,在这种情况下它不应该是cdt.TransDateTime=DATEPARTYear,2018,因为您在中没有使用过?所以,我刚刚在下面用EXISTS发布了另一个答案,但后来我意识到其他人都在以我从未见过的方式使用DATEPART。通常,第二个参数是某种日期。将2018传递到DATEPART函数中,不等于过去很遥远的一年,并且可能永远不会与交易匹配吗?嗨,应该是cdt.TransDateTime=DATEPARTYear,2018,在这种情况下,因为您没有在中使用过它吗?因此,我只是在下面使用EXISTS发布了另一个答案,但后来我意识到其他人都在以一种我从未见过的方式使用DATEPART。通常,第二个参数是某种日期。将2018年传递到DATEPART函数中,不就是一个遥远的过去并且可能永远不会匹配事务的年份吗?这将更好cdt.TransDateTime>='2018-01-01'和cdt.TransDateTime<'2019-01-01'@Pரதீப் 您认为它会更好地优化吗?DATEPART将使查询不可搜索。@Pரதீப் 谢谢你说得对。我更新了我的答案以反映这一点。不知何故,我一直认为SQLServer在这里进行了某种优化。老实说,我通常会使用一个范围,并尽量远离函数调用。这会更好cdt.TransDateTime>='2018-01-01'和cdt.TransDateTime<'2019-01-01'@Pரதீப் 您认为它会更好地优化吗?DATEPART将使查询不可搜索。@Pரதீப் 谢谢你说得对。我更新了我的答案以反映这一点。不知何故,我一直认为SQLServer在这里进行了某种优化。老实说,我通常会使用一个范围,并尽量远离函数调用。