Sql select语句中的分类
我有这张桌子Sql select语句中的分类,sql,oracle,group-by,case,categories,Sql,Oracle,Group By,Case,Categories,我有这张桌子 id | object | type -------------------------------- 1 | blue | color 1 | burger | food 2 | sandwich | food 2 | red | color 2 | coke | beverage 3 |
id | object | type
--------------------------------
1 | blue | color
1 | burger | food
2 | sandwich | food
2 | red | color
2 | coke | beverage
3 | sprite | beverage
3 | coke | beverage
3 | red | color
4 | bacon | food
我必须创建一个select语句,该语句将显示一个包含id、颜色、食品和饮料列的表。由ID安排,上面有他们指定的东西
所以我的预期结果是
id | color | food | beverage
-------------------------------------------
1 | blue | burger |
2 | red | sandwich | coke
3 | red | | sprite
3 | | | coke
4 | | bacon |
到现在为止,我有这个代码
Select id as id,
Case When I.Type = 'color' Then I.Object End As color,
Case When I.Type = 'food' Then I.Object End As food,
Case When I.Type = 'beverage' Then I.Object End As beverage
From table I
order by id
但我的代码的问题是它不按ID分组,所以它为每个对象创建多行
蒂亚 您正在寻找pivot查询。问题的挑战在于,对于给定的
id
和type
,可能存在多个对象。要处理此问题,您可以首先使用listag
对给定类型的CSV聚合对象执行groupby
查询:
SELECT id,
MAX(CASE WHEN t.type = 'color' THEN t.object ELSE NULL END) AS color,
MAX(CASE WHEN t.type = 'food' THEN t.object ELSE NULL END) AS food,
MAX(CASE WHEN t.type = 'beverage' THEN t.object ELSE NULL END) AS beverage
FROM
(
SELECT id,
LISTAGG(object, ',') WITHIN GROUP (ORDER BY object) AS object,
type
FROM yourTable
GROUP BY id, type
) t
GROUP BY t.id
内部查询首先跨id
和type
聚合对象,外部查询是一个简单的pivot查询,正如您所期望的那样
下面是一个小提琴图,它显示了MySQL中几乎相同的查询(Oracle似乎永远被破坏):
试试这个
我已经实现了使用子句
您可以尝试以下方法:
with test(id, object, type) as
(
select 1,'blue', 'color' from dual union all
select 1,'burger', 'food' from dual union all
select 2,'sandwich','food' from dual union all
select 2,'red', 'color' from dual union all
select 2,'coke', 'beverage' from dual union all
select 3,'sprite', 'beverage' from dual union all
select 3,'coke', 'beverage' from dual union all
select 3,'red', 'color' from dual union all
select 4,'bacon', 'food' from dual
)
select id,
max( case when type = 'color'
then object
else null
end
) as color,
max( case when type = 'food'
then object
else null
end
) as food,
max( case when type = 'beverage'
then object
else null
end
) as beverage
from (
select id, object, type, row_number() over ( partition by id, type order by object) row_for_id
from test
)
group by id, row_for_id
order by id, row_for_id
内部查询是主要部分,处理单个id
与多个类型对象的情况;您可以通过编辑按对象排序
来修改排序。
外部查询可以以不同的方式重新编写,例如使用透视
;我使用了MAX
,希望把它弄清楚。罗宾:我对你的评论(根据蒂姆·比格莱森的回答)部分是错误的。有一个基于枢轴的解决方案;然而,“组”不是按id划分的,而是按id划分的,在你的三个“类别”中排名。要使此解决方案(或任何不使用动态SQL的解决方案)正常工作,必须事先知道所有“类型”(及其名称),并且必须在SQL查询中对它们进行硬编码
注意:在这个解决方案中,我假设对于每个id,相同“类型”中的“对象”根据字母顺序相互关联(因此,例如,对于id=3,“coke”与“red”关联,“sprite”与NULL关联,与示例输出不同)。我在您的问题下方向您询问了这一点-如果您没有与我们共享其他规则,需要不同类型的对象的不同配对,则可能会也可能不会调整解决方案以满足这些其他规则
编辑:仔细看,这几乎就是Aleksej提供的,没有使用显式的pivot
语法。他的解决方案的优点是,它可以在较旧版本的Oracle中工作(在11.1之前,pivot
首次可用)
查询(包括第一个CTE中的测试数据):
输出:
ID COLOR FOOD BEVERAGE
---- -------- -------- --------
1 blue burger
2 red sandwich coke
3 red coke
3 sprite
4 bacon
它不会显示所有的对象。每个id只有一行正在启动。你能告诉我pivot查询如何处理我的问题吗@tim@robing-pivot
不是您问题的解决方案。在pivot
操作中,每个id只能得到一行pivot
是一种聚合操作,类似于sum
和count
——每个组只能得到一个结果。再说一遍:你要做的不是一个pivot
操作。@mathguy总是很高兴看到你对我的答案发表评论。如果OP可以接受CSV对象,那么pivot没有问题。正如你自己所说,建议的输出不是相关的,所以这个答案是解决这个问题的一种方法。@TimBiegeleisen-我实际上是在回答OP;你的答案上写的是个意外。其他人也建议采用pivot
;OP选择在你的回答中抓住这一点,但它可能在其他地方。我对OP的观点是:要么你想要一个id可能不止一行,要么你想要一个pivot
解决方案;不能两者都有。根据什么规则,“精灵”与“红色”关联,“可乐”与id=3的NULL关联?为什么不换个方向呢?它是随机的吗(因此其他人解决同一个问题可能会得到不同的解决方案,两种解决方案同样有效)?还是有其他规定?
with
inputs ( id, object, type ) as (
select 1, 'blue' , 'color' from dual union all
select 1, 'burger' , 'food' from dual union all
select 2, 'sandwich' , 'food' from dual union all
select 2, 'red' , 'color' from dual union all
select 2, 'coke' , 'beverage' from dual union all
select 3, 'sprite' , 'beverage' from dual union all
select 3, 'coke' , 'beverage' from dual union all
select 3, 'red' , 'color' from dual union all
select 4, 'bacon' , 'food' from dual
),
r ( id, object, type, rn ) as (
select id, object, type, row_number() over (partition by id, type order by object)
from inputs
)
select id, color, food, beverage
from r
pivot ( max(object) for type in ( 'color' as color, 'food' as food,
'beverage' as beverage))
order by id, rn
;
ID COLOR FOOD BEVERAGE
---- -------- -------- --------
1 blue burger
2 red sandwich coke
3 red coke
3 sprite
4 bacon