SQL查询 - 链接到一次查找两个字段

时间:2014-03-28 17:04:34

标签: sql oracle11g

我想整理一个查询,将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是否为空,如何返回所有值?

2 个答案:

答案 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;

以下是我对您的代码所做的更改:

  1. 您正在使用INNER JOIN第二次加入中执行REF_CODE,因此NULL值会从结果中删除。我将其更改为LEFT JOIN

  2. 您的第二个问题归结为filter criteriaONWHERE条款中的展示位置。

  3. 第二点的解释:

    INNER JOIN中,您可以互换使用ONWHERE。底层逻辑不会改变,也不会对执行计划产生影响。

    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;