修改多条件案例的选择查询

时间:2019-01-30 04:46:22

标签: sql sql-server tsql

我有下表dbo.Product

Name Amount
----------
A     10
B      4
C      6
D      3
A      7

我有条件:如果名称等于“ A”,则显示代码“ X”,折扣为“ 10%”,否则显示代码“ Y”,折扣为“ 5%”

我想修改以下查询,您能否建议更好的解决方案:

select 
    case p.Name 
       when 'A' then 'X' else 'Y' end as Code,
    case p.Name 
       when 'A' then (p.Amount * 0.1) else (p.Amount * 0.05) end as Discount,
    p.Name,
    p.Amount
from 
    dbo.Product as P

3 个答案:

答案 0 :(得分:2)

一种方法是:

Select 
    p.Name,
    p.Amount,
    'X' as Code,
    p.Amount * 0.1 as Discount
from 
    dbo.Product as P
where p.Name = 'A'
Union All
Select 
    p.Name,
    p.Amount,
    'Y' as Code,
    p.Amount * 0.05 as Discount
from 
    dbo.Product as P
where p.Name != 'A'; 

!=在SQL Server中: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/not-equal-to-transact-sql-exclamation?view=sql-server-2017

数据库小提琴:

Select @@version;

Create Table Product (Name varchar(1), Amount money);

Insert into Product values ('A', 10);
Insert into Product values ('B', 4);
Insert into Product values ('C', 6);
Insert into Product values ('D', 3);
Insert into Product values ('A', 7);

Select 
    case p.Name 
       when 'A' then 'X' else 'Y' end as Code,
    case p.Name 
       when 'A' then (p.Amount * 0.1) else (p.Amount * 0.05) end as Discount,
    p.Name,
    p.Amount
from 
    Product as P;

Select 
    'X' as Code,
    p.Amount * 0.1 as Discount,
    p.Name,
    p.Amount
from 
    dbo.Product as P
where p.Name = 'A'
Union all
Select 
    'Y' as Code,
    p.Amount * 0.05 as Discount,
    p.Name,
    p.Amount
from 
    dbo.Product as P
where p.Name != 'A';

答案 1 :(得分:2)

还有其他编写此查询的方法-但在select子句中使用case表达式似乎是最佳选择。
我已将您的样本数据并乘以840行,以便对性能有一些了解。然后,我测试了三种不同的方法来获得预期的结果:

首先,来自问题的查询-它在这三个方面均表现最佳。 第二,Gauravsa建议的并集所有查询,第三,交叉应用版本。

(在我的服务器上)结果如下:

案例表达:16%
全部合并:36%
交叉申请:48%

从结果中可以清楚地看到,case表达式版本是迄今为止的赢家-主要是因为与表扫描或索引扫描甚至是索引查找相比,计算标量的操作非常便宜。

请注意,我已经在没有索引的临时表上进行了测试,因此使用真实实时数据进行的测试可能会产生不同的结果-但是我不认为结果的顺序会发生变化-我的意思是,大小写表达式版本可能仍然会赢。

比起说来,从2012年版本开始,有一种写简单的case表达式的较短方法:IFF函数。

select 
    IIF(p.Name = 'A', 'X', 'Y') as Code,
    IIF(p.Name = 'A', 0.1, 0.05) * p.Amount as Discount,
    p.Name,
    p.Amount
from 
    #Product as P

此查询与问题中的查询完全相同-只需较少的代码。

这是我测试中的完整脚本,因此任何人都可以重复该脚本或以我测试的方式发现问题:(the result execution plan can be found here)

-- Create sample data
create table #Product
(
    Name char(1),
    Amount int
);

insert into #Product (Name, Amount) values
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),
('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7),('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7), ('A', 10), ('B', 4), ('C', 6), ('D', 3), ('A', 7);

-- Cross apply version: nice trick, too slow.
select 
    Code,
    Discount,
    p.Name,
    p.Amount
from 
    #Product as P
cross apply
(
   select 'X' as code, p.Amount * 0.1 As Discount
   where p.Name = 'A'
   union all
   select 'Y', p.Amount * 0.5
   where p.Name <> 'A'
) x

-- Case expression: OP's query
select 
    case p.Name 
       when 'A' then 'X' else 'Y' end as Code,
    case p.Name 
       when 'A' then (p.Amount * 0.1) else (p.Amount * 0.05) end as Discount,
    p.Name,
    p.Amount
from 
    #Product as P

-- Union all - Gauravsa's query
select 
    p.Name,
    p.Amount,
    'X' as Code,
    p.Amount * 0.1 as Discount
from 
    #Product as P
where p.Name = 'A'
union all
select 
    p.Name,
    p.Amount,
    'Y' as Code,
    p.Amount * 0.05 as Discount
from 
    #Product as P
where p.Name != 'A'

-- Clean up
drop table #Product

答案 2 :(得分:0)

在如下所示的单个查询中尝试此操作

Select 
     p.Name,
     p.Amount,
     CASE WHEN p.Name = 'A' THEN 'X' ELSE 'Y' END as Code,
     CASE WHEN p.Name <> 'A' THEN (p.Amount * 0.1) ELSE (p.Amount * 0.05) END as Discount,
from dbo.Product as P