Хотел выбрать из таблицы, но игнорирует ее - PullRequest
0 голосов
/ 23 апреля 2019

Я хочу иметь оператор выбора, который принимает параметр таблицы идентификаторов.Желаемое поведение состоит в том, что если в таблице нет элементов, получить все значения, но если в таблице есть элементы, выбирайте только те, чьи значения соответствуют параметру ID таблицы.

My where Предложение выглядит следующим образом:

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

Однако в результате всегда возвращаются все местоположения, даже если таблица LocationIds содержит одно значение и этот идентификатор соответствует только одному значению.

Я могу установитьзначения, такие как, но он по-прежнему возвращает все местоположения:

DECLARE @LocationIds TABLE
(
  ID int
)

INSERT INTO @LocationIds (ID)
VALUES (10227)

Ответы [ 3 ]

2 голосов
/ 23 апреля 2019

Лично я делаю это как 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и @EndTransDate являются date, а не datetime.Если они являются последними, то этот запрос вряд ли будет работать так, как вы хотите, в любом случае, и вам лучше использовать следующую логику:

WHERE TransactionDateTime >= @BeginTransDate
  AND TransactionDateTime < DATEADD(DAY, 1, @EndTransDate)
1 голос
/ 23 апреля 2019

Вам не хватает пары скобок.

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
1 голос
/ 23 апреля 2019

Попробуйте это:

SELECT * 
FROM BLAH
WHERE [TransactionDateTime] BETWEEN @BeginTransDate AND @EndTransDate 
AND (
      (SELECT COUNT(ID) FROM @LocationIds) = 0
      OR 
      ID in (SELECT ID FROM @LocationIds)
     )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...