2011-08-26 27 views
2

我試圖做同樣的事情到 How can I improve this SQL query?誤差與存儲過程中的邏輯

然而,有邏輯 基本上我有可能與他們有關聯的多個值ID的列表,這些值是是,否,或其他一些字符串。 對於ID x,如果其中任何一個值爲是,則x應該爲Yes,如果它們全部爲No,則它應該爲No,如果它們包含任何其他值但是yes和no,則顯示該值。我只想每個ID返回1行,不重複。

,但在我的邏輯,如果所有的值都是肯定的,那麼顯示是,如果所有值都沒有那麼不顯示,如果是肯定的混合,沒有或其他任何顯示混合

DECLARE @tempTable table (ID int, Val varchar(1)) 

    INSERT INTO @tempTable (ID, Val) VALUES (10, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (11, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (11, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (12, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (12, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (12, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (13, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (14, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (14, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (15, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (16, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (17, 'F') 
    INSERT INTO @tempTable (ID, Val) VALUES (18, 'P') 


    SELECT DISTINCT t.ID, COALESCE(t2.Val, t3.Val, t4.Val) 
    FROM @tempTable t 
    LEFT JOIN 
    (
     SELECT ID, Val 
     FROM @tempTable 
     WHERE Val = 'Y' 
    ) t2 ON t.ID = t2.ID 
    LEFT JOIN 
    (
     SELECT 
     ID, Val FROM @tempTable 
     WHERE Val = 'N' 
    ) t3 ON t.ID = t3.ID 
    LEFT JOIN 
    (
     SELECT ID, Val 
     FROM @tempTable 
     WHERE Val <> 'Y' AND Val <> 'N' 
    ) t4 ON t.ID = t4.ID 

Update dbo.households 
SET dbo.households.code = #TempTable.code 
FROM #TempTable 
WHERE dbo.households.id = #TempTable.id 
+1

什麼問題? – akonsu

+0

由於某種原因,如果結果出現N,N,P它仍然顯示N或者如果它出來Y,N它將顯示Y.我想Y,Y出來作爲Y和N,N出來作爲N和其他所有出來'M' –

回答

5
SELECT ID , 
     CASE WHEN MAX(Val) = MIN(Val) 
        AND MAX(Val) IN ('N', 'Y') THEN MAX(Val) 
      ELSE 'M' 
     END 
FROM @tempTable 
GROUP BY ID 

或返回一個版本Y如果任何存在,而不是如果所有Y

SELECT ID , 
     ISNULL(MAX(CASE WHEN Val = 'Y' THEN 'Y' END), 
       CASE WHEN MAX(Val) = MIN(Val) THEN MAX(Val) 
           ELSE 'M' 
         END) 
FROM @tempTable 
GROUP BY ID 

或者說需要字面上的「,如果他們包含任何其他值,但yes和no,顯示最終版本那個價值。「聲明。

SELECT ID , 
     ISNULL(MAX(CASE WHEN Val = 'Y' THEN 'Y'END), 
       ISNULL(MAX(CASE WHEN Val NOT IN ('N', 'Y') THEN Val END), 
         MAX(Val))) 
FROM @tempTable 
GROUP BY ID 
+0

+1 - 非常簡單的解決方案! – JNK

+0

'M'從哪裏來?他的問題表明'如果他們包含任何其他值,但是是和否,**顯示該值**。'此外,您只檢查最大值是'Y'還是'N'...並且沒有真正檢查其他潛在值。 'P'將評估高於'N'但低於'Y'。 – canon

+0

@Martin,這仍然顯得過時。您需要與其他值分開確定Y/N ...您當前的解決方案已損壞,併爲id 14返回'M'(而不是'Y')。 – canon

2

你可以使用max(),因爲它是一個char值。此得到掄:

注:這裏所採用的邏輯是,非Y/N>任何Y> n只有

[編輯]重構&簡化:

select 
t.ID 
,isnull(max(nyn.Val),max(yn.Val)) as Val 
from @tempTable as t  
    left join @tempTable as nyn -- Non-Y/N value 
    on nyn.ID = t.ID 
    and nyn.Val not in ('Y','N') 
    left join @tempTable as yn -- Y/N value 
    on yn.ID = t.ID 
    and yn.Val in ('Y','N') 
group by t.ID 

產生以下結果:

ID Val 
10 Y 
11 N 
12 Y 
13 N 
14 Y 
15 Y 
16 Y 
17 F 
18 P 
+0

謝謝,但由於某種原因,我的更新聲明不工作,但結果時,我執行查詢是。所以基本上我現在得到正確的結果,但我的更新查詢給我舊值 –

+0

我的解決方案仍然會返回具有多個非Y/N值的ID的多個記錄...所以你可能想要決定什麼邏輯您想要申請過濾多個匹配。 – canon

+0

啊,所以如果一條記錄同時有y和n,你會返回兩行嗎? –

0

另一種方法。我使用MAX()以防一個以上的值返回除Y和N以外的其他值。

SELECT 
    ID, 
    CASE 
    WHEN EXISTS(SELECT 1 FROM @tempTable tt WHERE t.ID = tt.ID AND tt.Val = 'Y') 
      THEN 'Y' 
    WHEN EXISTS(SELECT 1 FROM @tempTable tt WHERE t.ID = tt.ID AND tt.Val NOT IN ('Y','N')) 
      THEN (SELECT MAX(Val) FROM @tempTable tt WHERE t.ID = tt.ID AND tt.Val NOT IN ('Y','N')) 
    ELSE 'N' 
    END   
FROM @tempTable t 
GROUP BY ID