SQL查询-链接到同时具有两个字段的查找

SQL查询-链接到同时具有两个字段的查找,sql,oracle11g,Sql,Oracle11g,我想组合一个查询,将治疗表中的两个字段链接到我的查找表REF_代码;字段保护(可以为空)和字段类型(非空)。REF_代码包含多个查找类别,以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

我想组合一个查询,将治疗表中的两个字段链接到我的查找表REF_代码;字段保护(可以为空)和字段类型(非空)。REF_代码包含多个查找类别,以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';
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;
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'
有两个治疗记录,其中EVENT_ID=1234。此查询仅返回PROT不为null的记录。PROT=null的记录根本不会返回

为什么会这样?无论PROT是否为null,如何返回所有值?

试试这个

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;

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

  • 您正在使用
    REF\u code
    第二次连接中执行
    内部连接
    ,因此
    NULL
    值将从结果中删除。我把它改成了左连接

  • 您的第二个问题归结为您的
    筛选条件
    ON
    WHERE
    子句中的位置

  • 对第二点的解释:

    内部联接中
    ,可以互换使用
    上的
    中的
    。底层逻辑不会改变,也不会对执行计划产生影响

    对于
    外部联接
    ,情况完全不同。正如您在案例中所看到的,错误放置的过滤器可能会完全扭曲逻辑

    a<代码>WHERE子句中的筛选条件

    SELECT * FROM A left join B
    ON A.id=B.id
    WHERE B.id=1
    
    SELECT * FROM A left join B
    ON A.id=B.id
    AND B.id=1
    
    上述查询的功能类似于
    内部联接
    ,并将整个结果仅限于
    B.id=1
    的行(请注意,过滤器应用于
    左联接
    运算符右侧的表)

    b<代码>ON子句中的筛选条件

    SELECT * FROM A left join B
    ON A.id=B.id
    WHERE B.id=1
    
    SELECT * FROM A left join B
    ON A.id=B.id
    AND B.id=1
    
    上面的查询只会限制
    表B
    的行,因为它们在
    左联接
    操作符中映射到
    表A
    。因此,结果将包含
    表A
    所有行,以及
    表B
    列中的值,仅包含与条件
    B.id=1
    匹配的行。我创建了一个查询来测试您的问题。请检查以验证它是否符合您的场景

    where子句胜过了左连接。将Cat_ID上的两个筛选器移动到join子句中,如下所示:

    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';
    
    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;
    
    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'
    
    另一种不太干净的方法是用
    isnull()
    将where子句中与左连接相关的部分包围起来,如下所示:

    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';
    
    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;
    
    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'
    
    有关详细信息,请参见此类似答案

    其他:

    如果@SoulTrain的查询有效,那么您必须在Ther中有与Ref\u Code中的行不匹配的行。在这种情况下,确实需要使用两个左联接,但联接的顺序并不重要。请参阅以查看此查询的操作。这是最后一个查询

    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;
    

    您使用的是什么版本的SQL?顺便说一句,可能与使用Oracle 11g的版本相同……嗨,亚伯拉罕。不幸的是,第一个示例不起作用-仍然排除PROT=null的记录。我遗漏了什么?这个答案有用吗?唯一不同的是,他在连接子句中使用了括号。让我知道这是否有帮助,我会更新答案。我看不出为什么此语句不能获得所需的记录。将标准移动到on子句可以解决此问题。加入顺序在这里并不重要。r1和r2之间没有关系。达维梅尔,你的问题在别的地方。从查询中删除r2时,您是否获得记录?或者,在删除r1时,您是否获得了这些信息?请检查并仔细考虑您的查询。@davemere-我添加了一个SQLFiddle示例来模拟您描述的场景。请查看链接。我还修改了第二个查询的语法,使用Coalesce而不是ISNULL。这有用吗?@ThorstenKettner谢谢你支持我。数据中一定有其他内容。谢谢SoulTrain…但我担心这仍然无法返回PROT=null的记录。不知道我在这里错过了什么。。。!我想我知道是什么导致了你的情况。你能试试更新后的代码,看看它是否有效吗。如果有效,我将解释更改。您的
    Where
    子句限制了结果集。检查更新的code.SoulTrain,太棒了!这个查询似乎与我非常相似……只是WHERE子句位于不同的位置。你能解释一下为什么会这样吗?当然。。。我稍后会解释。