使用 CASE 语句问题选择聚合数据
Posted
技术标签:
【中文标题】使用 CASE 语句问题选择聚合数据【英文标题】:SELECTING aggregate data using CASE statement issue 【发布时间】:2016-07-21 19:30:24 【问题描述】:我正在尝试创建查询以获取区域数据,以准备将列移动到另一个表。我们的数据库是如何建立的,我们有资产和电缆。一个资产可以有很多电缆,但一个电缆不能有多个资产。我们目前正在尝试将 Zone 字段从 Cable 表(例如下面)移动到 Asset 表。
A_ID C_ID Zone
--------------------------
1 1 Green
1 2 Green
1 3 Yellow
2 4 Green
2 5 Red
3 6 Yellow
3 7 Yellow
3 8 Yellow
3 9 Red
我希望为资产表设置它的方式是,如果资产包含具有不同区域的多条电缆,如果其中一个区域为黄色,则默认为黄色(例如 3 根绿色电缆,1 根黄色电缆 - Asset_ID有黄色区域)。接下来,如果它没有任何黄色但至少有 1 条红色,则默认为红色(例如 2 条绿色电缆,3 条红色电缆 - Asset_ID 具有红色区域)。只有当它只有绿色区域时,它才会默认为绿色。
使用上面的示例表,这些是我所期望的结果。
Expected Results
A_ID Zone
-------------
1 Yellow
2 Red
3 Yellow
我正在尝试使用 CASE 语句,但我在制定查询以正确分组结果时遇到了困难。
任何帮助将不胜感激,在此先感谢您。
【问题讨论】:
尝试使用具有窗口功能的 CTE。像 RowNum 之类的东西(当黄色然后 1,红色然后 2,绿色 3 时按案例区域按资产顺序分区),然后在外部查询中从每个组中选择第一行。 【参考方案1】:一种使用条件聚合和case
表达式的方法。
select a_id
,case when yellow_count >=1 then 'Yellow'
when yellow_count = 0 and red_count >=1 then 'Red'
when yellow_count = 0 and red_count = 0 and green_count >=1 then 'Green'
end zone
from (select a_id,
count(case when zone = 'Yellow' then 1 end) yellow_count,
count(case when zone = 'Red' then 1 end) red_count
count(case when zone = 'Green' then 1 end) green_count
from cable_table
group by a_id) t
【讨论】:
你不认为 count 和 case 会比 join 和 row_number() 慢吗?【参考方案2】:不需要 case 或 if 语句。分组思考。您需要为优先级分配一个优先级连接,并首先选择具有最高优先级的连接。像这样
WITH Priority AS
(
SELECT * FROM (
VALUES
('Yellow', 1),
('Red', 2),
('Green', 3)
) AS P(Zone,P)
)
SELECT A_ID, Zone
FROM (
SELECT A_ID, Zone
ROW_NUMBER() OVER (PARTITION BY A_ID ORDER BY P.P ASC) AS RN
FROM AssetTable A
LEFT JOIN Priority P ON A.Zone = P.Zone
) SUB
WHERE RN = 1
不确定我的语法是否适用于 CTE for Oracle 中的 VALUES。如果出现错误,请替换为:
WITH Priority AS
(
SELECT 'Yellow' AS Zone, 1 AS P
UNION ALL
SELECT 'Red' AS Zone, 2 AS P
UNION ALL
SELECT 'Green' AS Zone, 3 AS P
)
【讨论】:
【参考方案3】:为什么不做一个简单的:
SELECT A_ID, MAX( Zone )
FROM table
GROUP BY A_ID
如果某个 A_ID 具有 Yellow
,则 max( Zone ) 返回 Yellow
如果某个 A_ID 没有Yellow
,但有Red
,则 max(Zone) 返回 Red<br>
otherwise (no
Yellownor
Red) max( Zone ) returns
Green`
和例子:
with data as (
select 1 a_id, 1 c_id , 'Green' zone from dual union all
select 1 , 2 , 'Green' from dual union all
select 1 , 3, 'Yellow' from dual union all
select 2 , 4 , 'Green' from dual union all
select 2 , 5 , 'Red' from dual union all
select 3 , 6 , 'Yellow' from dual union all
select 3 , 7 , 'Yellow' from dual union all
select 3 , 8 , 'Yellow' from dual union all
select 3 , 9 , 'Red' from dual
)
select a_id, max( zone )
from data
group by a_id
A_ID MAX(ZO
---------- ------
1 Yellow
2 Red
3 Yellow
【讨论】:
以上是关于使用 CASE 语句问题选择聚合数据的主要内容,如果未能解决你的问题,请参考以下文章