Ari*_*ian 4 sql t-sql sql-server left-join sql-server-2008
我有这个问题:
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
Run Code Online (Sandbox Code Playgroud)
表#tmp_rep有2列(Q_ID,Q_Desc)和4 行.表po_Questions有10个在证书行列中使用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
Run Code Online (Sandbox Code Playgroud)
然后我在结果中只获得3行,而Q_ID = 4不属于结果.为什么SQL Server有这种行为?
谢谢
对于非匹配的行po.UserName
会NULL
如此LEN(LTRIM(RTRIM(po.UserName)))
是NULL
NULL > 0
当谓词出现在你正在将你的外部联接转回内部联接时,评估结果UNKNOWN
不是TRUE
这样WHERE
.类似于FUNCS
SQLMenace指出的那样.
您可能想要下载Itzik Ben Gan的逻辑查询处理海报.
从概念上讲,会发生以下情况(但不应将其与物理实现的方式混淆!)
对于您的第一个查询:
#tmp_rep
,po_Questions
ON Filter
应用有效地执行INNER JOIN
打开Q_ID = Certificate
但也排除po_Questions
与谓词不匹配的任何行.Outer
Rows from #tmp_rep
添加回来.这些将包含NULL
所有列 po_Questions
WHERE
条款,所以这是最终的结果.对于您的第二个查询:
#tmp_rep
,po_Questions
ON Filter
应用有效地INNER JOIN
开启Q_ID = Certificate
.Outer
Rows from #tmp_rep
添加回来.这些将包含NULL
所有列 po_Questions
WHERE
评估该子句.这肯定会删除上一步中的所有行,也可能删除其他行.