我想整理一个查询,将THERAPY表中的两个字段链接到我的查找表REF_CODE;字段PROT(可以为null)和字段THER_TYPE(非空)。 REF_CODE包含多个查找类别,由CAT_ID区分。我此刻的查询如下:
SELECT THER_ID, r1.CODE_NAME, r2.CODE_NAME
FROM THER t
LEFT JOIN REF_CODE r1 ON t.PROT = r1.CODE
JOIN REF_CODE r2 ON t.THER_TYPE = r2.CODE
WHERE EVENT_ID = 1234
AND r1.CAT_ID = '1'
AND r2.CAT_ID = '2';
有两个THERAPY记录,其中EVENT_ID = 1234.此查询仅返回PROT不为空的记录。 PROT = null的记录根本没有返回。
这是为什么?无论PROT是否为空,如何返回所有值?
答案 0 :(得分:1)
试试这个..
SELECT THER_ID, r1.CODE_NAME, r2.CODE_NAME
FROM THER t
LEFT JOIN REF_CODE r1 ON t.PROT = r1.CODE
and r1.CAT_ID = '1'
LEFT JOIN REF_CODE r2 ON t.THER_TYPE = r2.CODE
AND r2.CAT_ID = '2'
WHERE EVENT_ID = 1234;
以下是我对您的代码所做的更改:
您正在使用INNER JOIN
在第二次加入中执行REF_CODE
,因此NULL
值会从结果中删除。我将其更改为LEFT JOIN
您的第二个问题归结为filter criteria
在ON
和WHERE
条款中的展示位置。
第二点的解释:
在INNER JOIN
中,您可以互换使用ON
和WHERE
。底层逻辑不会改变,也不会对执行计划产生影响。
与OUTER JOINs
完全不同。正如您在案例中所看到的,错误的过滤器可能会完全扭曲逻辑。
一个。 Filter Criteria in the WHERE Clause
即
SELECT * FROM A left join B
ON A.id=B.id
WHERE B.id=1
上述查询的作用类似于INNER JOIN
,并且仅将整个结果限制为B.id=1
的行(请注意,过滤器应用于LEFT JOIN
右侧的表格操作者)
湾Filter Criteria in the ON Clause
即
SELECT * FROM A left join B
ON A.id=B.id
AND B.id=1
上述查询只会限制table B
行,因为它们会映射到table A
运算符中的LEFT JOIN
。因此,结果将包含table A
的所有行以及table B
列中的值仅适用于符合条件B.id=1
的行
答案 1 :(得分:1)
我创建了一个SQL Fiddle查询来测试您的问题。请检查以确认它符合您的方案。
where子句胜过左连接。将Cat_ID上的两个过滤器移动到连接子句中,如下所示:
SELECT THER_ID, r1.CODE_NAME, r2.CODE_NAME as Name2
FROM THER t
LEFT JOIN REF_CODE r1 ON t.PROT = r1.CODE AND r1.CAT_ID = '1'
JOIN REF_CODE r2 ON t.THER_TYPE = r2.CODE AND r2.CAT_ID = '2'
WHERE EVENT_ID = 1234;
另一种不太干净的方法是用isnull()
包围与左连接相关的where子句的部分,如下所示:
SELECT THER_ID, r1.CODE_NAME, r2.CODE_NAME as Name2
FROM THER t
LEFT JOIN REF_CODE r1 ON t.PROT = r1.CODE
JOIN REF_CODE r2 ON t.THER_TYPE = r2.CODE AND r2.CAT_ID = '2'
WHERE EVENT_ID = 1234
AND Coalesce(RTRIM(r1.CAT_ID),'1') = '1'
请参阅Left Outer Join Not Working的类似答案。
其他:
如果@ SoulTrain的查询有效,那么您还必须在 Ther 中包含 Ref_Code 中没有匹配行的行。在这种情况下,您确实需要使用两个左连接,但连接的顺序无关紧要。请参阅updated SQL Fiddle Example以查看此查询的实际效果。这是最后一个查询。
SELECT THER_ID, r1.CODE_NAME, r2.CODE_NAME
FROM THER t
LEFT JOIN REF_CODE r1 ON t.PROT = r1.CODE and r1.Cat_ID = 1
LEFT JOIN REF_CODE r2 ON t.THER_TYPE = r2.CODE AND r2.CAT_ID = '2'
WHERE EVENT_ID = 1234;