Sql server SQL Server:左外部联接,如果存在值,则返回Y或N

Sql server SQL Server:左外部联接,如果存在值,则返回Y或N,sql-server,join,unique,case,max,Sql Server,Join,Unique,Case,Max,我有一个查询,显示了一组关于人的信息,以及他们是否曾经有过一组DX代码。每列是同一表格中另一组DXCODE的不同检查: 示例输出: pid . . . .HTN . . .DM 123 . . . Y . . . . .N 456 . . . N . . . . .N 查询: select p.pid ,CASE WHEN HTN.pid is not null THEN 'Y' ELSE 'N' END AS HTN ,... (other ca

我有一个查询,显示了一组关于人的信息,以及他们是否曾经有过一组DX代码。每列是同一表格中另一组DXCODE的不同检查:

示例输出:

pid . . . .HTN . . .DM  
123 . . . Y . . . . .N  
456 . . . N . . . . .N  
查询:

select  
    p.pid
    ,CASE WHEN HTN.pid is not null THEN 'Y' ELSE 'N' END AS HTN   
    ,... (other case statements)
from p

left outer join (  
    SELECT dx.pid, max(create_timestamp) as maxdate  
    FROM pdx  
    WHERE pdx.dxcode IN ('401','401.0','401.1','401.9')  
    group by dx.pid  
    ) as HTN on p.pid = HTN.pid
…同一pdx表上的其他联接以查询是否存在其他dx代码

我的查询是有效的,但我认为它并没有达到应有的效率。我真的不需要maxdate做任何事情,但它起作用了。在此之前,我使用的是selectdistinct-person,但我意识到它需要做多少后处理,查询性能已经大大提高了。对于最佳实践,我认为使用max只返回一个结果的额外计算仍然是不必要的计算

我尝试使用exists、left joins、top 1和case语句的变体来做同样的事情,但我只是没有正确地执行代码


谢谢。我知道这必须是一个简单的答案。我一直在搜索的术语并没有得到我所希望的答案。

也许可以将您的CASE语句更改为类似于当HTN.pid不为空时,则1或0结束,对每个CASE求和,然后围绕整件事进行最终选择?然后,例如,当HTN>0时,是否为N

select
    pid,
    case when HTN > 0 then 'Y' else 'N' end AS 'HTN',
    case when DM > 0 then 'Y' else 'N' end AS 'DM',
    case when CBG > 0 then 'Y' else 'N' end AS 'CBG',
    case when XYZ > 0 then 'Y' else 'N' end AS 'XYZ',
    case when DB > 0 then 'Y' else 'N' end AS 'DB'
from (  
        select
            p.pid,
            sum(case when pdx.dxcode in ('409', '409.1', '409.3') then 1 else 0 end) as 'HTN',
            sum(case when pdx.dxcode in ('899', '899.1', '892.2') then 1 else 0 end) as 'DM',
            sum(case when pdx.dxcode in ('410.0', '419.1', '419.3') then 1 else 0 end) as 'CBG',
            sum(case when pdx.dxcode in ('250', '250.1', '250.3') then 1 else 0 end) as 'XYZ',
            sum(case when pdx.dxcode in ('58.0', '58.1', '58.3') then 1 else 0 end) as 'DB'
        from
            person p left join
            pdx on
                p.pid = pdx.pid
        group by p.pid
    ) as dx

不确定这是否更有效,但看起来更简单

SELECT
 p.pid,
 MAX(CASE WHEN pdx.dxcode IN ('401','401.0','401.1','401.9') THEN 'Y' ELSE 'N' END) AS HTN,
 MAX(CASE WHEN pdx.dxcode IN ('501','501.0','501.1','501.9') THEN 'Y' ELSE 'N' END) AS DM,
 MAX(CASE WHEN pdx.dxcode IN ('601') THEN 'Y' ELSE 'N' END) AS XN
FROM p
LEFT OUTER JOIN pdx ON p.pid = pdx.pid
GROUP BY
 p.pid

更新:

如果您希望去掉最大值,使其在第一次正匹配时停止,请尝试此操作

SELECT
 DISTINCT
 p.pid,
 CASE WHEN EXISTS (SELECT 1 FROM pdx WHERE p.pid = pdx.pid AND pdx.dxcode IN ('401','401.0','401.1','401.9')) THEN 'Y' ELSE 'N' END AS HTN,
 CASE WHEN EXISTS (SELECT 1 FROM pdx WHERE p.pid = pdx.pid AND pdx.dxcode IN ('501','501.0','501.1','501.9')) THEN 'Y' ELSE 'N' END AS DM,
 CASE WHEN EXISTS (SELECT 1 FROM pdx WHERE p.pid = pdx.pid AND pdx.dxcode IN ('601')) THEN 'Y' ELSE 'N' END AS XN
FROM p
;
您可以尝试这样做,它将首先获得不同的pid,然后为每个pid找到第一个正匹配项

WITH pd AS (SELECT DISTINCT p.pid FROM p)
SELECT
 pd.pid,
 CASE WHEN EXISTS (SELECT 1 FROM pdx WHERE pd.pid = pdx.pid AND pdx.dxcode IN ('401','401.0','401.1','401.9')) THEN 'Y' ELSE 'N' END AS HTN,
 CASE WHEN EXISTS (SELECT 1 FROM pdx WHERE pd.pid = pdx.pid AND pdx.dxcode IN ('501','501.0','501.1','501.9')) THEN 'Y' ELSE 'N' END AS DM,
 CASE WHEN EXISTS (SELECT 1 FROM pdx WHERE pd.pid = pdx.pid AND pdx.dxcode IN ('601')) THEN 'Y' ELSE 'N' END AS XN
FROM pd 
GROUP BY
 pd.pid
;

Nice Q-从我所看到的,查询计划中似乎忽略了
max()
,因此嵌套的select与
select pdx.pid相同。。按pdx.pid分组
。我不是100%确定,但我可以想象SQL在至少为此人找到一个诊断后就会停止计算。我们所有3个示例都使用max或sum。必须有一种方法可以做到这一点,而不需要对表格进行全面的检查。我只假设top或exist在第一次出现时停止。我很喜欢你的设计,因为它确实更干净。我更新了我的答案,加入了更多可能有用的例子。当然,您必须根据您的数据集对它们进行测试,以查看它们的实际性能。+1-虽然更新的答案可以简化,但假设p.pid是主键,因为我们不再在外循环中加入pdx,所以可以删除distinct and组。更新的SqlFiddle:奇怪的是,SqlFiddle的计划表明这4个查询都有相同的查询计划,成本为.0144,也就是说,除了提高可读性之外,对原始查询没有任何真正的改进。我们所有3个示例都使用max或sum。必须有一种方法可以做到这一点,而不需要对表格进行全面的检查。我只假设top或exist在第一次出现时停止。我认为你的会稍微快一点,因为它在处理表格时会进行汇总,不会产生临时表格(猜测)。这很有趣,因为他们都很有效率。我猜你的会快一点。