2016-01-26 60 views
0

我有一個表,讓我們把它values與主鍵和五個整數字段,如:T-SQL:選擇行其中至少兩個字段匹配條件

id val1 val2 val3 val4 val5 
1 4  3  4  5  3 
2 2  3  2  2  2 
3 5  4  1  3  3 
4 1  4  3  4  4 

現在我需要選擇5個值字段中至少任意兩個值都爲4的所有行。所以結果集應該包含第一行(id = 1)和最後一行(id = 4)。

我從一個簡單的OR條件開始,但有太多的組合。然後我試着用HAVING和COUNT進行子選擇,但沒有成功。

任何想法如何解決這個問題?

回答

8

您可以使用VALUES構建一個包含您的字段的內聯表。然後查詢該表以獲得具有至少兩個領域的平等行4:

SELECT * 
FROM mytable 
CROSS APPLY (
    SELECT COUNT(*) AS cnt 
    FROM (VALUES (val1), (val2), (val3), (val4), (val5)) AS t(v) 
    WHERE t.v = 4) AS x 
WHERE x.cnt >= 2 

Demo here

+0

好的解決方案。我會選擇這種方式,因爲CROSS APPLY比UNPIVOT更爲我熟悉。謝謝! – Ulli

2

這是微不足道的解決,如果你的數據是標準化的 - 所以讓我們用UNPIVOT標準化的數據,然後解決它:

declare @t table (id int not null, val1 int not null, val2 int not null, 
        val3 int not null, val4 int not null, val5 int not null) 
insert into @t(id,val1,val2,val3,val4,val5) values 
(1,4,3,4,5,3), 
(2,2,3,2,2,2), 
(3,5,4,1,3,3), 
(4,1,4,3,4,4) 

select 
    id 
from 
    @t t 
     unpivot 
    (valness for colness in (val1,val2,val3,val4,val5)) r 
group by id 
having SUM(CASE WHEN valness=4 THEN 1 ELSE 0 END) >= 2 

結果:

id 
------- 
1 
4 

當然,你可能會想出比valnesscolness更好的名字,這些名字描述的是這些數據(存儲的數字和列名中嵌入的數字)實際上是什麼

+0

不錯。似乎工作。謝謝。 – Ulli

5

雖然cross apply快,這可能是稍快於簡單地使用case

select t.* 
from t 
where ((case when val1 = 4 then 1 else 0 end) + 
     (case when val2 = 4 then 1 else 0 end) + 
     (case when val3 = 4 then 1 else 0 end) + 
     (case when val4 = 4 then 1 else 0 end) + 
     (case when val5 = 4 then 1 else 0 end) 
    ) >= 2; 

我也注意到,case是ANSI標準的SQL和提供基本上每個數據庫。

相關問題