具有INTERSECT,占位符值的多个SQL SELECT WHERE

时间:2017-05-05 17:58:37

标签: sql-server select intersect

我正在使用SQL Server,并尝试执行以下操作:

SELECT dword FROM Details WHERE dskey = '51a'
INTERSECT
SELECT dword FROM Details WHERE dskey = '52b'
INTERSECT
SELECT dword FROM Details WHERE dskey = '53i'
INTERSECT
SELECT dword FROM Details WHERE dskey = '54d'
INTERSECT
SELECT dword FROM Details WHERE dskey = '55e';

这很好用。但是,我需要构建一个通用的SELECT,如:

SELECT dword FROM Details WHERE dskey = value1
INTERSECT
SELECT dword FROM Details WHERE dskey = value2
INTERSECT
SELECT dword FROM Details WHERE dskey = value3
INTERSECT
SELECT dword FROM Details WHERE dskey = value4
INTERSECT
SELECT dword FROM Details WHERE dskey = value5;

然而,在任何给定的执行中,我可能都没有获得所有五个关键值。我需要一些虚拟键值,不会干扰他的INTERSECT。

例如,假设我只有1个值,其余4个为空。但是INTERSECT没有(正确地)起作用。

无论如何都有虚拟值不会干扰INTERSECTS。

我讨厌必须做嵌套ifs,如果我只有一个值,我只执行一个SELECT。如果我有两个值,那么我有两个SELECTS,介入INTERSECT等等。

以下是这一切:

假设我有一个5个字符的单词,我希望能够在SELECT WHERE中返回一个说明所有5个字符单词的列表,其中包含' i'在第三位。很容易。然后我可能想要选择第三个位置是' i'第五个是' e。这类似于"财富之轮"。我可能有五个值a-b-i-d-e所以返回的集合应该只有。因此,如果有一组5个SELECTS和4个介入INTERSECTS,这个构造可以处理1到5个值,那将是很好的。

我尝试过NULL值,但显然不能正常工作。

2 个答案:

答案 0 :(得分:3)

您还可以将查询构造为:

SELECT dword
FROM Details
WHERE dskey IN (value1, value2, value3, value4, value5)
GROUP BY dword
HAVING COUNT(DISTINCT dskey) = 5;

您仍然需要替换IN列表和数字5.您可以使用显式参数来编写它:

WITH vals as (
      SELECT v.val
      FROM (VALUES (@value1), (@value2), (@value3), (@value4), (@value5)) v(val)
    )
SELECT dword
FROM Details d JOIN
     vals
     ON d.dskey = vals.val
GROUP BY dword
HAVING COUNT(DISTINCT dskey) = (SELECT COUNT(*) FROM vals);

这是完全可参数化的并处理NULL值。

编辑:

实际上,您也可以使用您的版本执行此操作:

SELECT dword FROM Details WHERE dskey = @value1 or @value1 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value2 or @value2 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value3 or @value3 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value4 or @value4 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value5 or @value5 IS NULL;

将所有行相交是交叉无操作。

答案 1 :(得分:0)

戈登这就像一个魅力!

use wofwords;
go

DECLARE @value1 varchar(25) = '51a';
DECLARE @value2 varchar(25) = '52b';
DECLARE @value3 varchar(25) = NULL;
DECLARE @value4 varchar(25) = NULL;
DECLARE @value5 varchar(25) = NULL;


SELECT dword FROM Details WHERE dskey = @value1 or @value1 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value2 or @value2 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value3 or @value3 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value4 or @value4 IS NULL
INTERSECT
SELECT dword FROM Details WHERE dskey = @value5 or @value5 IS NULL;
go

它给了我正确的答案,最重要的是,我现在可以编写c#部分并且只有一个查询而不是嵌套的ifs ...

约翰尼