Sql 有没有一种更有效的方法可以在这个特定的上下文中编写我的过滤器?
我使用的是Sql 有没有一种更有效的方法可以在这个特定的上下文中编写我的过滤器?,sql,sql-server,tsql,select,unpivot,Sql,Sql Server,Tsql,Select,Unpivot,我使用的是SQL Server 2014,我的数据库中有一个表(t1),其中包含一个数字列表(n1到n6)。摘录如下: Id n1 n2 n3 n4 n5 n6 100 3 10 26 31 35 39 101 1 3 11 22 36 40 102 10 19 20 30 39 40 103 6 12 25 27 28 33 ... 假设我想通过排除存在数字3和19的行来过
SQL Server 2014
,我的数据库中有一个表(t1
),其中包含一个数字列表(n1到n6)。摘录如下:
Id n1 n2 n3 n4 n5 n6
100 3 10 26 31 35 39
101 1 3 11 22 36 40
102 10 19 20 30 39 40
103 6 12 25 27 28 33
...
假设我想通过排除存在数字3和19的行来过滤掉这个表,我的过滤代码如下所示:
Select * from t1
WHERE [n1] not in (3,19)
AND [n2] not in (3,19)
AND [n3] not in (3,19)
AND [n4] not in (3,19)
AND [n5] not in (3,19)
AND [n6] not in (3,19)
--sample data
WITH smple ( id, n1, n2, n3, n4, n5, n6) AS
( SELECT 100, 3, 10, 26, 31, 35, 39
union all
select 101,1,3,11,22,36,40
union all
select
102,10,19,20,30,39,40
union all
select
103,6,12,25,27,28,33
),
--end sample data
not_vals (n) as (select 3 union all select 19 )
SELECT
s.*
FROM
smple s
EXCEPT
SELECT
s.*
FROM
smple s join not_vals nv on
nv.n IN ( s.n1, s.n2, s.n3, s.n4, s.n5, s.n6)
;
预期产出:
Id n1 n2 n3 n4 n5 n6
103 6 12 25 27 28 33
...
有没有更有效的方法来编写我的过滤器?您的过滤器很好,但您可能会发现编写以下内容更简单:
where 3 not in (n1, n2, n3, n4, n5, n6) and
19 not in (n1, n2, n3, n4, n5, n6)
因为您使用不等式引用所有六列,所以无法真正提高性能。您可以修复数据模型,使列位于单独的行中,从而允许使用索引。一个选项使用
不存在和值()
当列表中的列数和/或值数增加时,这比原始查询的伸缩性更好—尽管这并不一定更有效
:
Id | n1 | n2 | n3 | n4 | n5 | n6
--: | -: | -: | -: | -: | -: | -:
103 | 6 | 12 | 25 | 27 | 28 | 33
Id | n1 | n2 | n3 | n4 | n5 | n6
--: | -: | -: | -: | -: | -: | -:
103 | 6 | 12 | 25 | 27 | 28 | 33
将不需要的值集放置在CTE中,并使用Except运算符
正如其他人所指出的,数据模型并不理想
要解决不在
中过滤效率低下的问题,您可以像这样使用EXCEPT操作符:
Select * from t1
WHERE [n1] not in (3,19)
AND [n2] not in (3,19)
AND [n3] not in (3,19)
AND [n4] not in (3,19)
AND [n5] not in (3,19)
AND [n6] not in (3,19)
--sample data
WITH smple ( id, n1, n2, n3, n4, n5, n6) AS
( SELECT 100, 3, 10, 26, 31, 35, 39
union all
select 101,1,3,11,22,36,40
union all
select
102,10,19,20,30,39,40
union all
select
103,6,12,25,27,28,33
),
--end sample data
not_vals (n) as (select 3 union all select 19 )
SELECT
s.*
FROM
smple s
EXCEPT
SELECT
s.*
FROM
smple s join not_vals nv on
nv.n IN ( s.n1, s.n2, s.n3, s.n4, s.n5, s.n6)
;
从性能的角度来看可以使用的各种方法的效率是很有趣的
最终的解决方案应该具有良好的性能,因此相关子查询可能不会提供这种性能
下面是一个相关子查询:
--sample data
with smple ( id, n1, n2, n3, n4, n5, n6) AS
( SELECT 100, 3, 10, 26, 31, 35, 39
union all
select 101,1,3,11,22,36,40
union all
select
102,10,19,20,30,39,40
union all
select
103,6,12,25,27,28,33
),
--end sample data
not_vals (n) as (select 3 union all select 19 )
SELECT
s.*
FROM
smple s
WHERE
NOT EXISTS (
SELECT 1 FROM not_vals nv
WHERE
nv.n IN ( s.n1, s.n2, s.n3, s.n4, s.n5, s.n6)
)
;