问题
I'm using SQL Server and am trying to do the following:
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';
This works fine. However, I need to build a generic SELECT like:
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;
However, at any given execution I probably won't have all five key values. I need someway to have dummy key values that won't interfere with he INTERSECTs.
For example, say I have only 1 value, the remaining 4 are null. But the INTERSECT doesn't (correctly) work.
Is there anyway to have dummy values that won't interfere with the INTERSECTS.
I hate to have to do nested ifs where if I only have one value I only perform one SELECT. If I have two values then I have two SELECTS with an intervening INTERSECT and so on.
Here is what this is all about:
Say I have a 5 character word, I want to be able to do a SELECT WHERE to return a list of say all 5 character words that have 'i' in the third position. Easy enough. Then I may want to SELECT where the third position is 'i' and fifth is 'e'. This resembles "Wheel of Fortune". I may have all five values a-b-i-d-e so the returned set only should be abide. Hence, it would be nice to have one set of 5 SELECTS with four intervening INTERSECTS that this construct could handle 1 to 5 values.
I've tried NULL values and that clearly doesn't work as it shouldn't.
回答1:
You can also construct the query as:
SELECT dword
FROM Details
WHERE dskey IN (value1, value2, value3, value4, value5)
GROUP BY dword
HAVING COUNT(DISTINCT dskey) = 5;
You still need to replace the IN
list and the number 5. You could write this using explicit parameters:
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);
This is fully parameterizable and handles NULL
values.
EDIT:
Actually, you can do this with your version as well:
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;
Intersecting all the rows is an intersection no-op.
回答2:
Gordon this worked like a charm!
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
It gives me the correct answers and best of all, I can now code up the c# part and have a single query instead of nested ifs...
Johnny
来源:https://stackoverflow.com/questions/43811171/multiple-sql-select-where-with-intersect-placeholder-value