2016-01-26 61 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和提供基本上每个数据库。

相关问题