SQL Server, выбирая из двух таблиц, используя оператор IF внутри оператора WHERE, в зависимости от параметра - PullRequest
2 голосов
/ 16 февраля 2010

Как я могу сделать следующее в SQL Server

DECLARE @Local nvarchar(20)
SET @Local = 'True'

    SELECT * FROM My_Table
    WHERE my_ID IN

    (IF @Local = 'True' 
         SELECT AllIDs FROM ATable
    ELSE 
         SELECT TeamIDs FROM TeamTable
    )

Ответы [ 4 ]

2 голосов
/ 16 февраля 2010

Перейти на союз: -

SELECT * FROM My_Table WHERE my_id IN
(
  SELECT AllIDs AS MyIDs FROM ATable WHERE @Local = 'True'
  UNION
  SELECT TeamIDs AS MyIDs FROM TeamTable WHERE @Local <> 'True'
)
1 голос
/ 16 февраля 2010

Не делай этого!

(по крайней мере, если вы не заботитесь о производительности)

Конечно, есть способ сделать это, но вы на самом деле не должны этого делать - причина в том, что (в общем случае) один оператор имеет только 1 план выполнения, однако у вас по существу есть 2 (потенциально очень разные) запросы:

SELECT * FROM My_Table
WHERE my_ID IN (SELECT AllIDs FROM ATable)

SELECT * FROM My_Table
WHERE my_ID IN (SELECT AllIDs FROM TeamTable)

Объединение этих двух запросов означает, что SQL-сервер вынужден одновременно пытаться оптимизировать оба из них, используя только 1 план действий. В зависимости от того, насколько различны эти две таблицы, это может работать нормально или может быть ужасно неправильным.

Например, если ATable содержит только 1 строку, а TeamTable содержит все идентификаторы в My_Table, то SQL-сервер должен выбрать / пойти на компромисс между поиском (лучше всего, если используется ATable) и сканирование таблицы (лучше всего, если используется TeamTable) - независимо от того, что он в итоге делает, SQL-сервер не может выполнить оба запроса, используя оптимальный план исполнения (если только оба плана исполнения не совпадают).

Вместо этого вы должны использовать 2 оператора:

DECLARE @Local nvarchar(20)
SET @Local = 'True'

IF @Local = 'True' 
    SELECT * FROM My_Table
    WHERE my_ID IN (SELECT AllIDs FROM ATable)
ELSE
    SELECT * FROM My_Table
    WHERE my_ID IN (SELECT AllIDs FROM TeamTable)

На самом деле в этом конкретном случае вам лучше выбрать список идентификаторов во временной таблице.

1 голос
/ 16 февраля 2010
DECLARE @Local nvarchar(20)
SET @Local = 'True'

SELECT * FROM My_Table
WHERE my_ID IN ( 
     SELECT AllIDs FROM ATable
     WHERE @Local = 'True'
     UNION ALL 
     SELECT TeamIDs FROM TeamTable
     WHERE @Local != 'True'
)
1 голос
/ 16 февраля 2010
SELECT  *
FROM    mytable
WHERE   my_id IN
        (
        SELECT  allids
        FROM    atable
        WHERE   @Local = 'True'
        )
UNION ALL
SELECT  *
FROM    mytable
WHERE   my_id IN
        (
        SELECT  teamids
        FROM    teamtable
        WHERE   COALESCE(@Local, '') <> 'True'
        )

Оптимизатор оптимизирует неправильный запрос, поэтому производительность будет соответствовать производительности соответствующего (оставшегося) запроса.

...