1

我有 2 个单独的 SQL 查询,但我不知道它们有何不同:

SELECT A.AccountName,
       T.Total
FROM   ACCOUNTS A
       LEFT OUTER JOIN (SELECT *
                        FROM   Totals
                        WHERE  PersonID = @PersonID
                               AND Yr = @Year) T
         ON A.AccountID = T.AccountID
ORDER  BY AccountName

SELECT A.AccountName,
       T.Total
FROM   ACCOUNTS A
       LEFT OUTER JOIN (SELECT *
                        FROM   Totals) T
         ON A.AccountID = T.AccountID
WHERE  PersonID = @PersonID
       AND Yr = @Year
ORDER  BY AccountName 

任何帮助将不胜感激。

4

3 回答 3

1

第一个查询将只显示所有客户记录的结果,无论客户是否有与您的@Year 和@Person 值匹配的总计记录(或者甚至是否根本不匹配总计记录)。对于不匹配的记录,Total 列的值为 NULL,但所有帐户都会有结果。第二个查询将仅显示总数与年份和人员匹配的帐户。如果没有匹配,帐户记录将根本不会出现在您的结果中。

并且 2 个查询真的应该写得更像这样(这里不需要子查询):

SELECT A.AccountName, T.Total
FROM   ACCOUNTS A
LEFT JOIN Totals T
         ON A.AccountID = T.AccountID AND T.PersonID = @PersonID AND T.Yr = @Year
ORDER  BY AccountName

SELECT A.AccountName, T.Total
FROM   ACCOUNTS A
LEFT JOIN Totals T ON A.AccountID = T.AccountID
WHERE  T.PersonID = @PersonID AND T.Yr = @Year
ORDER  BY AccountName 

上面的代码在功能上等同于您的原件。

最后,听起来你可能想要更像这样的东西:

SELECT A.AccountName, T.Total
FROM Accounts A
INNER JOIN Totals T ON T.AccountID = A.AccountID
WHERE T.PersonID = @PersonID AND T.Yr = @Year

在此查询中,您将 Year 和 Person 条件放在哪里并不重要。无论哪种方式,查询都将具有相同的结果:仅当与所需年份和人员的总计记录匹配时,才会显示客户记录。不匹配的帐户根本不会出现在结果中。

于 2012-10-03T16:41:18.363 回答
1

通过WHERE在外部联接(第二个查询)之后应用条件,您可能会从结果集中消除记录。第一个查询将包括ACCOUNTS表中的每一行。


也就是在第一个查询中,返回的表对于表中的每条记录都会至少有一行ACCOUNTSNULLs 表示表中没有匹配的数据Totals。如果表中有多个匹配Totals项,那么您将获得多行ACCOUNT

第二个查询将只返回ACCOUNTS与参数匹配的行,并且它们必须具有匹配的Totals行。

于 2012-10-03T16:41:22.663 回答
0

每当您为 OUTER JOIN 表添加简单子句时,您必须在测试条件之前测试外部表是否存在,否则,实际上,您将外部联接转换为内部联接。在你的情况下:

-- original
SELECT A.AccountName, T.Total
FROM ACCOUNTS A
LEFT OUTER JOIN (SELECT *
    FROM Totals
    WHERE PersonID = @PersonID
    AND Yr = @Year
) T ON A.AccountID = T.AccountID
ORDER  BY AccountName;

-- modified with same result
SELECT A.AccountName, T.Total
FROM ACCOUNTS A
LEFT OUTER JOIN Totals T ON A.AccountID = T.AccountID
WHERE (1=2 -- syntactic sugar
  OR (T.AccountID IS NULL) -- this prevents outer joined rows to be excluded
  OR (T.PersonID = @PersonID AND T.Yr = @Year) -- original filter
)
ORDER  BY AccountName;
于 2012-10-03T16:58:22.760 回答