Условный оператор в SQL, где предложение - PullRequest
7 голосов
/ 02 апреля 2010

Я хотел бы сделать что-то вроде следующего в SQl Server 2005 (что, как я знаю, недопустимо) для моего предложения where. Иногда @teamID (передаваемый в хранимую процедуру) будет значением существующего teamID, в противном случае он всегда будет равен нулю, и мне нужны все строки из таблицы Team.

Я исследовал использование Case, и оператор должен указывать до или после всего оператора, что не позволяет мне использовать другой оператор, основанный на значении @teamid. Любые предложения, кроме дублирования моих избранных утверждений.

    declare @teamid int
    set @teamid = 0

    Select Team.teamID From Team
      case @teamid
         when 0 then 
            WHERE Team.teamID > 0
         else
            WHERE Team.teamID = @teamid
      end 

Ответы [ 5 ]

18 голосов
/ 02 апреля 2010

Вы можете сделать это без дела:

SELECT  Team.teamID 
FROM    Team
WHERE   (@teamid = 0 AND Team.teamID > 0)
        OR (@teamid <> 0 AND Team.teamID = @teamid)
5 голосов
/ 02 апреля 2010

Без использования динамического SQL наиболее эффективным вариантом является:

IF @teamid = 0
  BEGIN

    SELECT t.teamid
      FROM TEAM t
     WHERE t.teamid > 0

  END
ELSE
  BEGIN

    SELECT t.teamid
      FROM TEAM t
     WHERE t.teamid = @teamid

  END

Использование динамического SQL:

DECLARE @SQL NVARCHAR(4000)
   SET @SQL = 'SELECT t.teamid
                 FROM TEAM t
                WHERE 1 = 1 '

   SET @SQL = @SQL + CASE @teamid
                       WHEN 0 THEN ' AND t.teamid > 0 '
                       ELSE ' AND t.teamid = @teamid '
                     END

BEGIN

  EXEC sp_EXECUTESQL @SQL N'@teamid INT', @teamid

END

Остерегайтесь, что sp_EXECUTESQL кэширует план запроса, а EXEC - нет. Читать это: http://www.sommarskog.se/dynamic_sql.html

2 голосов
/ 03 апреля 2010

Даже проще, чем ответ Andomar, и если предположить, что id никогда не равен 0 (как для большинства идентификаторов с автоинкрементом), то равен

SELECT  Team.teamID 
FROM    Team
WHERE   @teamid = 0 or Team.teamID = @teamid;

Этот предикат всегда имеет значение true, когда @teamid равен нулю, а в противном случае - только true, когда он соответствует идентификатору команды конкретной строки.

Обратите внимание: это работает довольно эффективно на Sybase 11 или выше; он работал довольно неэффективно на MS SQL Server 2003; Я не знаю, как это работает в текущей версии MS SQL Server.

Также вы можете использовать чехол; Вы просто должны поместить case в предложении where, а не в предложении where в случае. Итак, ваш оригинальный запрос будет:

Select Team.teamID 
From Team
where 
   case when @teamid = 0 then 0 else Team.teamID end = @teamId;

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

Приведенная выше форма, скорее всего, будет переписана интеллектуальным оптимизатором запросов (ваш пробег зависит от вашей СУБД), чтобы использовать индекс, если @teamid не равен нулю.

2 голосов
/ 02 апреля 2010

А как же:

Select Team.teamID From Team Where (@teamid=0 and team.teamID>0) or (@teamid<>0 and team.teamid=@teamid)
0 голосов
/ 03 апреля 2010

Если бы вы могли рассматривать Null как все записи:

WHERE Team.teamID = ISNULL(@teamid, Team.teamID)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...