我想在我的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的子集。会发生什么?
答案 0 :(得分:13)
不幸的是,基本方法是重复自己。
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>
幸运的是,大多数RDBMS都足够聪明,不必多次评估条件。这只是多余的打字。
在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语句返回的值是固定的。匹配相同条件的所有记录在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
答案 1 :(得分:6)
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
;
答案 2 :(得分:6)
CASE
仅返回单个值。如初。
它也(几乎总是)短路,这意味着如果满足您的第一个条件,则不会运行其他检查。
答案 3 :(得分:2)
在您的情况下,您将使用两个案例陈述,每个陈述用于您想要返回的每个值。
答案 4 :(得分:1)
或者您可以
SELECT
String_to_array(CASE
WHEN <condition 1> THEN a1||','||b1
WHEN <condition 2> THEN a2||','||b2
ELSE a3||','||b3
END, ',') K
FROM <table>
答案 5 :(得分:0)
您可以使用与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 :(得分:0)
在SQL CASE子句中,应用第一个成功匹配的条件,并忽略任何后续匹配条件。
答案 7 :(得分:0)
您可以在“ case”表达式中的xml数据类型内返回多个值,然后将其提取,也可以使用“ 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
答案 8 :(得分:0)
根据您的用例,可以使用多个select语句的并集,而不是使用case语句,每个条件一个。
当我发现此问题时,我的目标是有条件地选择多个列。我不一定需要案例陈述,所以这就是我所做的。
例如:
SELECT
a1,
a2,
a3,
...
WHERE <condition 1>
AND (<other conditions>)
UNION
SELECT
b1,
b2,
b3,
...
WHERE <condition 2>
AND (<other conditions>)
UNION
SELECT
...
-- and so on
请确保一次一次恰好满足一个条件。
我正在使用Postgresql,并且查询计划程序非常聪明,即使where子句中的条件评估为false(即实际上只有一条select语句在运行),它也根本不会运行select语句。对我来说很表现。