我有这个问题:
SELECT Q_ID,
Q_DESC,
COUNT(Q_ID)
FROM #tmp_rep
LEFT OUTER JOIN po_Questions po
ON Q_ID = Certificate AND FUNCS = 1
AND LEN(LTRIM(RTRIM(po.UserName))) > 0
AND LEN(LTRIM(RTRIM(po.UserNumber))) > 0
GROUP BY
Q_ID,
Q_DESC
ORDER BY
Q_ID
表#tmp_rep有2列(Q_ID,Q_Desc)和4行。表po_Questions有10个在列Certificate 行中使用3个Q_ID代码。如果我运行这个查询,每件事都没问题,对于Q-ID = 4,我得到0表示计数,但是如果我用这种方式写了那个查询:
SELECT Q_ID,
Q_DESC,
COUNT(Q_ID)
FROM #tmp_rep
LEFT OUTER JOIN po_Questions po
ON Q_ID = Certificate
WHERE FUNCS = 1
AND LEN(LTRIM(RTRIM(po.UserName))) > 0
AND LEN(LTRIM(RTRIM(po.UserNumber))) > 0
GROUP BY
Q_ID,
Q_DESC
ORDER BY
Q_ID
然后我在结果中只得到3行,而Q_ID = 4不属于结果。为什么SQL Server有这种行为?
感谢
答案 0 :(得分:6)
对于不匹配的行po.UserName
将为NULL
,因此LEN(LTRIM(RTRIM(po.UserName)))
为NULL
NULL > 0
评估为UNKNOWN
而非TRUE
,因此当谓词位于WHERE
时,您将外部联接转回内部联接。类似于FUNCS
,正如SQLMenace指出的那样。
您可能想要下载Itzik Ben Gan's Logical Query Processing poster。
从概念上来说会发生以下情况(不应该将其与物理实施方式相混淆!)
第一次查询:
#tmp_rep
上的笛卡尔积,po_Questions
ON Filter
,它有效地INNER JOIN
Q_ID = Certificate
po_Questions
,但也排除了与您的谓词不匹配的任何Outer
行。#tmp_rep
中不匹配的NULL
行添加回来。po_Questions
WHERE
#tmp_rep
条款,因此这是最终结果。第二个问题:
po_Questions
上的笛卡尔积,ON Filter
INNER JOIN
,有效地Q_ID = Certificate
Outer
{/ 1}}。#tmp_rep
中不匹配的NULL
行添加回来。po_Questions
WHERE
答案 1 :(得分:2)
本质上你已经创建了一个内连接,改变了
WHERE FUNCS = 1
到
AND FUNCS = 1
无法在WHERE子句中指定左外连接,否则将被过滤掉
另一个问题是NULL上的LEN函数不会大于0