2013-08-01 49 views
2

我有一個是對人員和他們是否曾經有過一組dxcodes的存在顯示大量信息的查詢。每一列是用於在同一個表中的另一組dxcodes的不同檢查:SQL服務器:左外連接,並返回Y或N,如果存在一個值

示例輸出:

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碼存在

我的查詢工作,但我不認爲這是有效率,因爲它可以。我真的不需要任何東西,但它的工作。在此之前,我使用了精選不同的人員,但意識到需要進行多少後處理,並且查詢性能已經顯着提高。對於最佳實踐,我認爲使用max返回僅一個結果的額外計算仍然是不必要的計算。

我嘗試使用的變化存在,左連接,頂部11和case語句做同樣的事情,但我只是沒有正確執行代碼。

謝謝。我知道這應該是一個簡單的答案。我一直在尋找的術語並沒有得到我期待的答案。

+0

尼斯Q - 從我所看到的,'MAX()'似在查詢計劃將被忽略,以便嵌套選擇是一樣的'選擇pdx.pid .. GROUP BY pdx.pid'。我不是100%確定的,但是我會想象SQL一旦發現至少有一次該人的診斷就停止評估。 – StuartLC

回答

1

可能改變你的CASE語句類似WHEN HTN.pid IS NOT NULL THEN 1個ELSE 0 END,和每一種情況下,則環繞整個事情的最終選擇?那麼,例如,當HTN> 0 THEN Y ELSE 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 
+0

我們所有例子中的3個都是使用max或sum。有一種方法可以做到這一點,而無需進行需要對錶格進行全面審查的計算。我只在第一次出現時就假定有頂部或存在止損。我認爲你的速度會稍微快一些,因爲它在處理表格時不會產生臨時表格(猜測)。 這很有趣,因爲它們都非常高效。我的猜測是你的會更快一點。 – jawz101

2

不確定這是否更有效,但看起來更簡單。

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 

SQL Fiddle

UPDATE:

如果您正在尋找擺脫MAX,使其停止在正賽的第一個實例,那麼試試這個。

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第一,然後找到每一個第一個正賽。

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 
; 

SQL Fiddle for those 2

+0

我們所有例子中的3個都是使用max或sum。有一種方法可以做到這一點,而無需進行需要對錶格進行全面審查的計算。我只在第一次出現時就假定有頂部或存在止損。我喜歡你的設計,因爲它絕對清潔。 – jawz101

+0

我更新了我的答案,以包含更多可能有所幫助的示例。當然,你必須根據你的數據集對它們進行測試,看看它們實際上做得如何。 –

+0

+1 - 雖然更新後的答案可以簡化,但假設p.pid是主鍵,因爲我們不再加入外部循環中的pdx,可以刪除distinct和group。更新了SqlFiddle:http://sqlfiddle.com/#!6/118c8/20奇怪的是,SqlFiddle的計劃表明這4個查詢都具有相同的查詢計劃,成本爲0.0144,即對原始數據沒有真正的改進查詢,而不是提高可讀性。 – StuartLC