SQL查询语句

时间:2012-10-03 16:38:03

标签: sql

我有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 

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

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

这两个查询应该更像这样编写(这里不需要子查询):

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

在此查询中,将年份和人员条件放在何处并不重要。查询将以相同的方式产生相同的结果:仅当帐户记录与具有所需年份和人员的总计记录匹配时,才会显示该帐户记录。不匹配的帐户根本不会显示在结果中。

答案 1 :(得分:1)

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


也就是说,在第一个查询中,返回的表对ACCOUNTS表中的每个记录至少有一行,其中NULL s {{1}中没有匹配的数据表。如果Totals表中有多个匹配项,那么您将获得Totals的多个行。

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

答案 2 :(得分: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;