如何在 CASE 语句中分配多个值?
How to assign multiple values in CASE statement?
我需要根据 CASE 语句为 select 分配两个值。伪:
select
userid
, case
when name in ('A', 'B') then 'Apple'
when name in ('C', 'D') then 'Pear'
end as snack
from
table
;
我正在为 snack
赋值。但是可以说我还想根据相同的条件为另一个变量 drink
赋值。一种方法是重复上述操作:
select
userid
, case
when name in ('A', 'B') then 'Apple'
when name in ('C', 'D') then 'Pear'
end as snack
, case
when name in ('A', 'B') then 'Milk'
when name in ('C', 'D') then 'Cola'
end as drink
from
table
;
但是,如果我必须根据相同的条件分配更多的值,例如 food
、drink
、room
等,此代码将变得难以维护。
有更好的方法吗?我可以把它放在 SQL 函数中吗,就像您通常在另一种(脚本)语言中所做的那样,如果可以,您能解释一下怎么做吗?
功能会破坏性能。但是你可以使用 common-table-expression(cte):
with cte as
(
Select IsNameInList1 = case when name in ('A', 'B')
then 1 else 0 end,
IsNameInList2 = case when name in ('C', 'D')
then 1 else 0 end,
t.*
from table
)
select
userid
, case when IsNameInList1=1 then 'Apple'
when IsNameInList2=1 then 'Pear'
end as snack
, case when IsNameInList1=1 then 'Milk'
when IsNameInList2=1 then 'Cola'
end as drink
from
cte
;
这样你就只有一个地方可以维护了。
如果查询性能无关紧要并且您想使用这样的标量值函数:
CREATE FUNCTION [dbo].[IsNameInList1]
(
@name varchar(100)
)
RETURNS bit
AS
BEGIN
DECLARE @isNameInList bit
BEGIN
SET @isNameInList =
CASE WHEN @name in ('A', 'B')
THEN 1
ELSE 0
END
END
RETURN @isNameInList
END
然后你可以在你的查询中这样使用它:
select
userid
, case when dbo.IsNameInList1(name) = 1 then 'Apple'
when dbo.IsNameInList2(name) = 1 then 'Pear'
end as snack
from
table
;
但更有效的方法是使用真实的 table 来存储它们。
希望对您有所帮助
SELECT userid
,(CASE flag WHEN 1 THEN 'Apple' WHEN 2 THEN 'Pear' WHEN 3 THEN '..etc' END ) as snack
,(CASE flag WHEN 1 THEN 'Milk' WHEN 2 THEN 'Cola' WHEN 3 THEN '..etc' END ) as drink
FROM (
SELECT userid
,( CASE WHEN name IN ('A', 'B') THEN 1
WHEN name IN ('C', 'D') THEN 2
WHEN name IN ('X', 'Y') THEN 3
ELSE 0 END ) AS flag
FROM table ) t
在做这样的事情时,我倾向于使用带有 table valued constructor:
的连接
SELECT t.UserID,
s.Snack,
s.Drink
FROM Table AS T
LEFT JOIN
(VALUES
(1, 'Apple', 'Milk'),
(2, 'Pear', 'Cola')
) AS s (Condition, Snack, Drink)
ON s.Condition = CASE
WHEN t.name IN ('A', 'B') THEN 1
WHEN t.name IN ('C', 'D') THEN 2
END;
如果我需要添加更多条件或列,我发现这是最灵活的。
或更冗长,但也更灵活:
SELECT t.UserID,
s.Snack,
s.Drink
FROM Table AS T
LEFT JOIN
(VALUES
('A', 'Apple', 'Milk'),
('B', 'Apple', 'Milk'),
('C', 'Pear', 'Cola'),
('D', 'Pear', 'Cola')
) AS s (Name, Snack, Drink)
ON s.Name= t.name;
正如 Ganesh 在评论中建议的那样,我建议为此创建一个映射 table,然后只进行查找。更容易插入、维护和扩展 - 所有这些都具有更好的性能。
我需要根据 CASE 语句为 select 分配两个值。伪:
select
userid
, case
when name in ('A', 'B') then 'Apple'
when name in ('C', 'D') then 'Pear'
end as snack
from
table
;
我正在为 snack
赋值。但是可以说我还想根据相同的条件为另一个变量 drink
赋值。一种方法是重复上述操作:
select
userid
, case
when name in ('A', 'B') then 'Apple'
when name in ('C', 'D') then 'Pear'
end as snack
, case
when name in ('A', 'B') then 'Milk'
when name in ('C', 'D') then 'Cola'
end as drink
from
table
;
但是,如果我必须根据相同的条件分配更多的值,例如 food
、drink
、room
等,此代码将变得难以维护。
有更好的方法吗?我可以把它放在 SQL 函数中吗,就像您通常在另一种(脚本)语言中所做的那样,如果可以,您能解释一下怎么做吗?
功能会破坏性能。但是你可以使用 common-table-expression(cte):
with cte as
(
Select IsNameInList1 = case when name in ('A', 'B')
then 1 else 0 end,
IsNameInList2 = case when name in ('C', 'D')
then 1 else 0 end,
t.*
from table
)
select
userid
, case when IsNameInList1=1 then 'Apple'
when IsNameInList2=1 then 'Pear'
end as snack
, case when IsNameInList1=1 then 'Milk'
when IsNameInList2=1 then 'Cola'
end as drink
from
cte
;
这样你就只有一个地方可以维护了。
如果查询性能无关紧要并且您想使用这样的标量值函数:
CREATE FUNCTION [dbo].[IsNameInList1]
(
@name varchar(100)
)
RETURNS bit
AS
BEGIN
DECLARE @isNameInList bit
BEGIN
SET @isNameInList =
CASE WHEN @name in ('A', 'B')
THEN 1
ELSE 0
END
END
RETURN @isNameInList
END
然后你可以在你的查询中这样使用它:
select
userid
, case when dbo.IsNameInList1(name) = 1 then 'Apple'
when dbo.IsNameInList2(name) = 1 then 'Pear'
end as snack
from
table
;
但更有效的方法是使用真实的 table 来存储它们。
希望对您有所帮助
SELECT userid
,(CASE flag WHEN 1 THEN 'Apple' WHEN 2 THEN 'Pear' WHEN 3 THEN '..etc' END ) as snack
,(CASE flag WHEN 1 THEN 'Milk' WHEN 2 THEN 'Cola' WHEN 3 THEN '..etc' END ) as drink
FROM (
SELECT userid
,( CASE WHEN name IN ('A', 'B') THEN 1
WHEN name IN ('C', 'D') THEN 2
WHEN name IN ('X', 'Y') THEN 3
ELSE 0 END ) AS flag
FROM table ) t
在做这样的事情时,我倾向于使用带有 table valued constructor:
的连接SELECT t.UserID,
s.Snack,
s.Drink
FROM Table AS T
LEFT JOIN
(VALUES
(1, 'Apple', 'Milk'),
(2, 'Pear', 'Cola')
) AS s (Condition, Snack, Drink)
ON s.Condition = CASE
WHEN t.name IN ('A', 'B') THEN 1
WHEN t.name IN ('C', 'D') THEN 2
END;
如果我需要添加更多条件或列,我发现这是最灵活的。
或更冗长,但也更灵活:
SELECT t.UserID,
s.Snack,
s.Drink
FROM Table AS T
LEFT JOIN
(VALUES
('A', 'Apple', 'Milk'),
('B', 'Apple', 'Milk'),
('C', 'Pear', 'Cola'),
('D', 'Pear', 'Cola')
) AS s (Name, Snack, Drink)
ON s.Name= t.name;
正如 Ganesh 在评论中建议的那样,我建议为此创建一个映射 table,然后只进行查找。更容易插入、维护和扩展 - 所有这些都具有更好的性能。