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)
    )
;