Подтвердить что ты не робот

Case в SQL, как вернуть несколько переменных?

Я хотел бы вернуть несколько значений в мой оператор case, например:

SELECT
  CASE
    WHEN <condition 1> THEN <value1=a1, value2=b1>
    WHEN <condition 2> THEN <value1=a2, value2=b2>
    ELSE <value1=a3, value3=b3>
  END
FROM <table>

Конечно, я могу написать условие случая несколько раз, каждый раз возвращать одно значение. Однако, поскольку у меня есть много условий, нужно подходить, скажем 100. Нехорошо повторять условие случая снова и снова.

Еще один вопрос, который я хотел бы задать, что произойдет, если одна запись соответствует нескольким условиям? означает ли это, что он вернет все или только последний? например условие 1 может стать подмножеством условия 2. что произойдет?

4b9b3361

Ответ 1

Основным способом, к сожалению, является повторение.

SELECT
  CASE WHEN <condition 1> THEN <a1> WHEN <condition 2> THEN <a2> ELSE <a3> END,
  CASE WHEN <condition 1> THEN <b1> WHEN <condition 2> THEN <b2> ELSE <b3> END
FROM 
  <table> 

К счастью, большинство РСУБД достаточно умны, чтобы НЕ нужно было оценивать условия несколько раз. Это просто избыточная типизация.


В MS SQL Server (2005+) вы можете использовать CROSS APPLY в качестве альтернативы этому. Хотя я понятия не имею, насколько он эффективен...

SELECT
  *
FROM
  <table>
CROSS APPLY
  (
   SELECT a1, b1 WHERE <condition 1>
   UNION ALL
   SELECT a2, b2 WHERE <condition 2>
   UNION ALL
   SELECT a3, b3 WHERE <condition 3>
  )
  AS case_proxy

Заметным недостатком здесь является то, что эквивалент ELSE отсутствует, и поскольку все условия могут возвращать значения, их необходимо создать так, чтобы только один мог когда-либо быть истинным за раз.


ИЗМЕНИТЬ

Если ответ Yuck изменен на UNION, а не на подход JOIN, он становится очень похожим на это. Основное различие, однако, состоит в том, что это только сканирует входные данные один раз, а не один раз за условие (100 раз в вашем случае).


ИЗМЕНИТЬ

Я также заметил, что вы можете иметь в виду, что значения, возвращаемые оператором CASE, являются фиксированными. Все записи, которые соответствуют одному и тому же условию, получают точные значения sames в value1 и value2. Это можно было бы сформировать так...

WITH
  checked_data AS
(
  SELECT
    CASE WHEN <condition1> THEN 1
         WHEN <condition2> THEN 2
         WHEN <condition3> THEN 3
         ...
         ELSE                   100
    END AS condition_id,
    *
  FROM
    <table>
)
,
  results (condition_id, value1, value2) AS
(
   SELECT 1, a1, b1
   UNION ALL
   SELECT 2, a2, b2
   UNION ALL
   SELECT 3, a3, b3
   UNION ALL
   ...
   SELECT 100, a100, b100
)
SELECT
  *
FROM
  checked_data
INNER JOIN
  results
    ON results.condition_id = checked_data.condition_id

Ответ 2

Оператор

A CASE может возвращать только одно значение.

Возможно, вы сможете превратить это в подзапрос, а затем JOIN к любым другим отношениям, с которыми вы работаете. Например (с использованием SQL Server 2K5 + CTE):

WITH C1 AS (
  SELECT a1 AS value1, b1 AS value2
  FROM table
  WHERE condition1
), C2 AS (
  SELECT a2 AS value1, b2 AS value2
  FROM table
  WHERE condition2
), C3 AS (
  SELECT a3 AS value1, b3 AS value2
  FROM table
  WHERE condition3
)
SELECT value1, value2
FROM -- some table, joining C1, C2, C3 CTEs to get the cased values
;

Ответ 3

CASE по определению возвращает только одно значение. Когда-нибудь.

Это также (почти всегда) короткое замыкание, что означает, что если ваше первое условие выполнено, никакие другие проверки не выполняются.

Ответ 4

В вашем случае вы будете использовать два случая, один для каждого значения, которое вы хотите вернуть.

Ответ 5

Вы можете использовать подзаголовок в сочетании с UNION. Всякий раз, когда вы можете возвращать одни и те же поля для более чем одного условия, используйте OR с круглой скобкой, как в этом примере:

SELECT * FROM
  (SELECT val1, val2 FROM table1 WHERE (condition1 is true) 
                                    OR (condition2 is true))
UNION
SELECT * FROM
  (SELECT val5, val6 FROM table7 WHERE (condition9 is true) 
                                    OR (condition4 is true))

Ответ 6

В предложении SQL CASE применяется первое успешно согласованное условие, и любые последующие условия сопоставления игнорируются.

Ответ 7

Вы можете вернуть несколько значений внутри типа данных xml в выражении "case", а затем извлечь их, также доступен блок "else"

SELECT 
xmlcol.value('(value1)[1]', 'NVARCHAR(MAX)') AS value1,
xmlcol.value('(value2)[1]', 'NVARCHAR(MAX)') AS value2
FROM
(SELECT CASE
WHEN <condition 1> THEN
CAST((SELECT a1 AS value1, b1 AS value2 FOR XML PATH('')) AS XML)
WHEN <condition 2> THEN
CAST((SELECT a2 AS value1, b2 AS value2 FOR XML PATH('')) AS XML)
ELSE
CAST((SELECT a3 AS value1, b3 AS value2 FOR XML PATH('')) AS XML)
END AS xmlcol
FROM <table>) AS tmp