SQL Server: случай с оператором «НЕ В» - PullRequest
3 голосов
/ 16 ноября 2011

Я пытаюсь сделать оператор CASE в SQL Server (хранимая процедура), где я должен проверить, должен ли он получить какие-либо результаты из другой таблицы.

Я только что сделал это, чтобы проиллюстрировать пример (не работает!)

SELECT
    *
FROM
    cards
WHERE
    CardID = @CardID
    AND
    CardID = 
        CASE WHEN @AlreadyOnDeck = 1 THEN
            IN (
                    SELECT CardID FROM OnDeckTable WHERE CardID = @CardID
            )
        CASE WHEN @AlreadyOnDeck = 0 THEN
            NOT IN (
                    SELECT CardID FROM OnDeckTable WHERE CardID = @CardID
            )
        END

Мне нужно сделать дело IN / NOT IN в зависимости от @AlreadyOnDeck переменная

Ответы [ 4 ]

3 голосов
/ 17 ноября 2011

Аналогичен ответу Макса, но использует операторы CASE. (Может привести к несколько лучшему плану выполнения из-за короткого замыкания внешнего оператора CASE.)

SELECT
    *
FROM
    cards c
WHERE
    c.CardID = @CardID
    AND
    1 = (CASE WHEN @AlreadyOnDeck = 1 THEN 
                   (CASE WHEN EXISTS(select * OnDeckTable dt where dt.CardID = c.CardID) THEN 1 END)
              WHEN @AlreadyOnDeck = 0 THEN 
                   (CASE WHEN NOT EXISTS(select * from OnDeckTable dt where dt.CardID = c.CardID) THEN 1 END)       
        END)
2 голосов
/ 16 ноября 2011
SELECT
    *
FROM
    cards crd
WHERE
    CardID = @CardID
    AND
    (
    (@AlreadyOnDeck = 1 AND EXISTS(SELECT 1 FROM OnDeckTable dt WHERE dt.CardID = crd.CardID))
    OR
    (@AlreadyOnDeck = 0 AND NOT EXISTS(SELECT 1 FROM OnDeckTable dt WHERE dt.CardID = crd.CardID))
    )
2 голосов
/ 16 ноября 2011

Я думаю, что это будет работать, но не проверял (данные теста не предоставлены).

SELECT
    *
FROM
    cards
WHERE
    CardID = @CardID
    AND
    (
        exists (select 1 from OnDeckTable where CardId = @CardId and @AlreadyOnDeck = 1)
        or not exists (select 1 from OnDeckTable where CardId = @CardId and @AlreadyOnDeck = 0)
    )
1 голос
/ 16 ноября 2011

Я бы сделал это с помощью соединения следующим образом:

SELECT *
FROM cards c
LEFT JOIN OnDeckTable o ON c.CardID = o.CardID
WHERE c.CardID = @CardID
  AND (((@alreadyOnDeck = 0) AND (o.CardID is not null)) OR
      ((@alreadyOnDeck = 1) AND (o.CardID is null)))

Я считаю, что это будет быстрее, чем предложения подзапроса, но я не проверял.

Также обратите внимание,Я не тестировал приведенный выше код, он может содержать опечатки.

Самый быстрый способ решить эту проблему - заключить в один оператор if переменную @alreadyOnDeck, например:

if (@alreadyOnDeck = 1)
  -- select for this case
else
  -- select for this case.

Если ваш код находится в хранимой процедуре, это будет самый быстрый способ, входные данные не будут меняться во время запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...