Sql server SQL Server-可选where子句-空表值参数

Sql server SQL Server-可选where子句-空表值参数,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,我有三个TVP-A,B和C A永远不会是空的。B或C可以为空 AND SomeId IN (SELECT n FROM @A) -- First AND SomeId IN (SELECT n FROM @B) -- Second -- Make this optional AND SomeId IN (SELECT n FROM @C) -- Third -- Make this optional 我需要将第二个/第三个条件设置为可选。我已经尝试了很多方法,比如case,(SELECT..或

我有三个TVP-A,B和C

A永远不会是空的。B或C可以为空

AND
SomeId IN (SELECT n FROM @A) -- First
AND
SomeId IN (SELECT n FROM @B) -- Second -- Make this optional
AND
SomeId IN (SELECT n FROM @C) -- Third -- Make this optional

我需要将第二个/第三个条件设置为可选。我已经尝试了很多方法,比如
case,(SELECT..或@B=null)
,但是由于这些都是表值参数,所以它不起作用

尝试使用

AND
(
SomeId IN (SELECT n FROM @A) -- First
OR
SomeId IN (SELECT n FROM @B) -- Second -- Make this optional
OR
SomeId IN (SELECT n FROM @C) -- Third -- Make this optional
)

尝试使用

AND
(
SomeId IN (SELECT n FROM @A) -- First
OR
SomeId IN (SELECT n FROM @B) -- Second -- Make this optional
OR
SomeId IN (SELECT n FROM @C) -- Third -- Make this optional
)

如果只有第二个和第三个条件是可选的,请尝试此操作

AND SomeId IN (SELECT n FROM @A) -- First

OR

(
    SomeId IN (SELECT n FROM @B) -- Second -- Make this optional
    OR
    SomeId IN (SELECT n FROM @C) -- Third -- Make this optional
)

如果只有第二个和第三个条件是可选的,请尝试此操作

AND SomeId IN (SELECT n FROM @A) -- First

OR

(
    SomeId IN (SELECT n FROM @B) -- Second -- Make this optional
    OR
    SomeId IN (SELECT n FROM @C) -- Third -- Make this optional
)

我看到并设置了参数默认为NULL的存储过程

@A int = NULL,
@B int = NULL,
@C int = NULL
隐藏的代码将加载到参数中,@B和@C可以加载,也可以不加载

当您到达
WHERE
子句时,您将

SomeId IN (SELECT n FROM @A)
AND (SomeID IN (SELECT n FROM @B) OR @B IS NULL)
AND (SomeID IN (SELECT n FROM @C) OR @C IS NULL)

注意语法;它不是
@B=NULL
,而是
@B is NULL

我看到并设置了参数默认为NULL的存储过程

@A int = NULL,
@B int = NULL,
@C int = NULL
SELECT m.*, a.N, b.N, c.N FROM MyTable m
INNER JOIN @A a
    ON a.N = m.SomeId
LEFT JOIN @B b
    ON b.N = m.SomeId
LEFT JOIN @C c
    ON c.N = m.SomeId
隐藏的代码将加载到参数中,@B和@C可以加载,也可以不加载

当您到达
WHERE
子句时,您将

SomeId IN (SELECT n FROM @A)
AND (SomeID IN (SELECT n FROM @B) OR @B IS NULL)
AND (SomeID IN (SELECT n FROM @C) OR @C IS NULL)
注意语法;它不是
@B=NULL
,它是
@B是NULL

SELECT m.*, a.N, b.N, c.N FROM MyTable m
INNER JOIN @A a
    ON a.N = m.SomeId
LEFT JOIN @B b
    ON b.N = m.SomeId
LEFT JOIN @C c
    ON c.N = m.SomeId
因此,您试图获取所有与a匹配的记录,如果它们与b或c匹配,那么您可以对它们做些什么


因此,您正在尝试获取与a匹配的所有记录,如果它们与b或c匹配,则可以对它们进行处理。

尝试以下操作。它以与原始查询相同的查询开始,但对于两个“可选”TVP中的每一个,它都添加了一个UNION ALL以选择“SomeId”,仅当该特定TVP中现在有行时。如果TVP中有行,则保持将其用作过滤器的意图,否则它不会过滤掉该行

DECLARE @Main TABLE (ID INT);
INSERT INTO @Main (ID) VALUES (55);
INSERT INTO @Main (ID) VALUES (999);

DECLARE @TestA TABLE (Col1 INT);
INSERT INTO @TestA (Col1) VALUES (55);
INSERT INTO @TestA (Col1) VALUES (67855);
DECLARE @TestB TABLE (Col1 INT);
--INSERT INTO @TestB (Col1) VALUES (565);

SELECT tmp.ID
FROM @Main tmp
WHERE tmp.ID IN (SELECT Col1 FROM @TestA)
AND tmp.ID IN (
               SELECT Col1 FROM @TestB
               UNION ALL
               SELECT tmp.ID
               WHERE NOT EXISTS(SELECT * FROM @TestB)
              )

查询(将
插入@TestB
注释掉)返回
55
的值,因为@TestB是“可选的”。但是如果您取消注释将
插入@TestB
,则不会返回任何内容,因为@TestB不包含值
55

,请尝试以下操作。它以与原始查询相同的查询开始,但对于两个“可选”TVP中的每一个,它都添加了一个UNION ALL以选择“SomeId”,仅当该特定TVP中现在有行时。如果TVP中有行,则保持将其用作过滤器的意图,否则它不会过滤掉该行

DECLARE @Main TABLE (ID INT);
INSERT INTO @Main (ID) VALUES (55);
INSERT INTO @Main (ID) VALUES (999);

DECLARE @TestA TABLE (Col1 INT);
INSERT INTO @TestA (Col1) VALUES (55);
INSERT INTO @TestA (Col1) VALUES (67855);
DECLARE @TestB TABLE (Col1 INT);
--INSERT INTO @TestB (Col1) VALUES (565);

SELECT tmp.ID
FROM @Main tmp
WHERE tmp.ID IN (SELECT Col1 FROM @TestA)
AND tmp.ID IN (
               SELECT Col1 FROM @TestB
               UNION ALL
               SELECT tmp.ID
               WHERE NOT EXISTS(SELECT * FROM @TestB)
              )

查询(将
插入@TestB
注释掉)返回
55
的值,因为@TestB是“可选的”。但是如果您取消注释将
插入@TestB
,则不会返回任何内容,因为@TestB不包含值
55

,执行以下操作将更加简洁明了:

;WITH AllowedIds_CTE (SomeId) AS (
    SELECT n from @A
    UNION
    SELECT n from @B
    UNION
    SELECT n from @C
)
SELECT * FROM SomeTable O
JOIN AllowedIds_CTE A
    ON O.SomeId = A.SomeId;
多个嵌套子查询和
中的
操作的可读性和效率都不如与CTE/表的联接


如果性能是一个问题,
UNION
可以替换为
UNION ALL
,如果您知道您的
n
值在
@a
中是不同的,
@B
@C

执行以下操作将更加简洁明了:

;WITH AllowedIds_CTE (SomeId) AS (
    SELECT n from @A
    UNION
    SELECT n from @B
    UNION
    SELECT n from @C
)
SELECT * FROM SomeTable O
JOIN AllowedIds_CTE A
    ON O.SomeId = A.SomeId;
多个嵌套子查询和
中的
操作的可读性和效率都不如与CTE/表的联接


如果性能是一个问题,
UNION
可以替换为
UNION ALL
,如果您知道您的
n
值在
@a
@B
@C

之间是不同的,则可以用索引临时表替换此模型中的CTE()。这不起作用。@AseemGautam:我认为DWF走上了正确的轨道。类似于
SomeID IN(从@A中选择n)和(EXISTS(从@B中选择1)以及SomeID IN(从@B中选择n))
。。。这对您的目的不起作用吗?这些是表值参数。这不起作用。@AseemGautam:我认为DWF走上了正确的轨道。类似于
SomeID IN(从@A中选择n)和(EXISTS(从@B中选择1)以及SomeID IN(从@B中选择n))
。。。这不符合你的目的吗?它们不是参数。。它们是表变量,不是参数。。它们是表变量。