想要从表中选择,但忽略它

时间:2019-04-23 19:01:34

标签: sql sql-server tsql

我想要一个带有ID表参数的select语句。理想的行为是,如果表中没有元素,则获取所有值,但是如果表中有元素,则仅选择那些值与表的ID参数匹配的值。

我的$_.Value子句如下:

where

但是,结果始终会带回所有位置,即使LocationIds表包含一个值并且该ID仅匹配一个值。

我可以设置诸如的值,但它仍会带回所有位置:

SELECT * FROM BLAH
WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate AND
 ((SELECT COUNT(ID) FROM @LocationIds) = 0) OR (EXISTS (SELECT 1 FROM 
@LocationIds WHERE t.LocationId = ID))

3 个答案:

答案 0 :(得分:2)

我个人将这作为2个查询来进行,作为@LocationIds中有行时的查询计划,并且该查询计划的差异可能会很大,以至于计划的重用将不会对其他计划有利。得到:

IF (SELECT COUNT(*) FROM @LocationIds) = 0 BEGIN
    SELECT *
    FROM BLAH
    WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate;
END ELSE BEGIN
    SELECT *
    FROM BLAH B
    WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate
      AND EXISTS (SELECT 1
                  FROM @LocationIds L
                  WHERE B.LocationID = L.ID);
END

或者,您可以动态SQL来构建查询,具体取决于是否需要@LociationIDs的值:

DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT *' + NCHAR(13) + NCHAR(10) +
           N'FROM BLAH B' + NCHAR(13) + NCHAR(10) +
           N'WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate' +
           CASE WHEN (SELECT COUNT(*) FROM @LocationIds) = 0 THEN ';'
                                                             ELSE NCHAR(13) + NCHAR(10) +
                                                                  N'  AND EXISTS (SELECT 1' + NCHAR(13) + NCHAR(10) +
                                                                  N'              FROM @LocationIds L' + NCHAR(13) + NCHAR(10) +
                                                                  N'              WHERE B.LocationID = L.ID);'
           END;

EXEC sp_executesql @SQL, N'@BeginTransDate date, @EndTransDate date', @BeginTransDate = @BeginTransDate, @EndTransDate = @EndTransDate;

请注意,我猜测@BeginTransDate@EndTransDatedate,而不是datetime。如果它们是后者,那么无论如何该查询都不太可能工作,您最好使用以下逻辑:

WHERE TransactionDateTime >= @BeginTransDate
  AND TransactionDateTime < DATEADD(DAY, 1, @EndTransDate)

答案 1 :(得分:1)

尝试一下:

SELECT * 
FROM BLAH
WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate 
AND (
      (SELECT COUNT(ID) FROM @LocationIds) = 0
      OR 
      ID in (SELECT ID FROM @LocationIds)
     )

答案 2 :(得分:1)

您缺少一对方括号。

WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate AND
 ( ((SELECT COUNT(ID) FROM @LocationIds) = 0) OR (EXISTS (SELECT 1 FROM 
@LocationIds WHERE t.LocationId = ID)) )

LEFT JOIN可能是一个更简单的解决方案。

SELECT b.*
FROM BLAH b
LEFT JOIN @LocationIds l ON l.ID = b.LocationId