我有一张桌子,我们用主键和五个整数字段称它为values
,如下所示:
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
现在我需要选择五个值字段中至少任意两个得到值4的所有行。因此结果集应该包含第一行(id = 1)和最后一行(id = 4)。 / p>
我从简单的OR条件开始,但组合太多了。然后我尝试使用HAVING和COUNT进行子选择,但没有成功。
任何想法如何解决这个问题?
答案 0 :(得分: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
答案 1 :(得分: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,基本上每个数据库都可用。
答案 2 :(得分: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
当然,您可能会提出比valness
和colness
更好的名称来描述 这些数据(存储的数字和嵌入的数字)列名称)实际上是。