Sql 使用concat和decode在子选择中按顺序排序
假设我有两张桌子: 产品Sql 使用concat和decode在子选择中按顺序排序,sql,oracle,select,oracle11g,Sql,Oracle,Select,Oracle11g,假设我有两张桌子: 产品 product_id (other fields are of no concern) Sku 我需要重写一个查询,该查询获取与该产品关联的所有颜色/颜色ID的产品ID列表,列表以逗号分隔。颜色ID/名称在两个列表中的顺序必须相同 期望输出: product_id colorIds colorNames 001 1,3,5 black,red,green 002 1,2,8,9 black,yellow,magenta
product_id (other fields are of no concern)
Sku
我需要重写一个查询,该查询获取与该产品关联的所有颜色/颜色ID的产品ID列表,列表以逗号分隔。颜色ID/名称在两个列表中的顺序必须相同
期望输出:
product_id colorIds colorNames
001 1,3,5 black,red,green
002 1,2,8,9 black,yellow,magenta,turquoise
请注意,颜色ID顺序的concat列表映射到颜色名称顺序
电流输出:
product_id colorIds colorNames
001 1,3,5 green,black,red -- out of order sometimes
002 1,2,8,9 black,yellow,magenta,turquoise
当前使用的查询:
select distinct(p.product_id) as product_id,
(select decode(dbms_lob.SubStr(wm_concat(DISTINCT color_name)),'NO COLOR','','No Color','','no color','',null,'',dbms_lob.SubStr(wm_concat(DISTINCT color_name))) as color_name from sku where product_id = p.product_id) as colorName,
(select decode(dbms_lob.SubStr(wm_concat(DISTINCT color_code)),'000','',dbms_lob.SubStr(wm_concat(DISTINCT color_code))) from sku where product_id = p.product_id) as colorCode
from product p;
我本想在这些子选择中添加ORDERBY子句,但查询出错了,说缺少右括号——奇怪的是,似乎没有不匹配的paren。欢迎提出任何建议
编辑*
上面的查询非常简单。实际上,它与十几个其他表连接,以获得与产品相关的其他数据列,其中大多数是非聚合数据段。解决方案不应在主查询中包含group by子句,也不应建议合理的方法来满足此要求。这可能适用于您:
SELECT p.product_id
, LISTAGG(s.color_id, ',') WITHIN GROUP ( ORDER BY s.color_id ) AS colorIds
, LISTAGG(s.color_name, ',') WITHIN GROUP ( ORDER BY s.color_id ) AS colorNames
FROM product p LEFT JOIN ( SELECT DISTINCT product_id, color_id, color_name FROM sku ) s
ON p.product_id = s.product_id
GROUP BY p.product_id
ORDER BY product_id
listag()
可以排序,而WM_CONCAT()
不能排序(并且它没有文档记录,等等)
根据OP对非聚合数据的评论更新:
WITH product_colors AS (
SELECT p.product_id
, LISTAGG(s.color_id, ',') WITHIN GROUP ( ORDER BY s.color_id ) AS colorIds
, LISTAGG(s.color_name, ',') WITHIN GROUP ( ORDER BY s.color_id ) AS colorNames
FROM product p LEFT JOIN ( SELECT DISTINCT product_id, color_id, color_name FROM sku ) s
ON p.product_id = s.product_id
GROUP BY p.product_id
)
SELECT t1.other_column, t2.other_column, etc.
FROM table1 t1 JOIN table2 t2 ON ...
JOIN product_colors pc ON ...
这将实现
distinct
效果(您不能将distinct
与listag
一起使用):
如果要显示产品
表中的列和/或要在产品
表中而不是在sku
表中显示产品,可以使用:
select p.product_id,
listagg(s.color_id, ',') within group(order by s.color_id) as colorids,
listagg(s.color_name, ',') within group(order by s.color_id) as colornames
from product p
left join (select distinct product_id, color_id, color_name from sku) s
on p.product_id = s.product_id
group by p.product_id
嗨,这也行
select product_id,
listagg(color_id,',') within group(order by color_names) as color_ids,
listagg(color_names,',') within group (order by color_names) color_names
from sku
group by product_id;
如果您使用的是Oracle 11g,那么您应该使用文档化的
listag()
,而不是未文档化的WM_CONCAT()
。。。仅供参考。给定的产品是否可以有2个以上相同颜色的SKU?如果是,您希望列表中的颜色重复,还是只显示一次?还有,你为什么要为产品表烦恼呢?您没有从中选择任何列。您实际上是在完整查询中从中选择列,还是因为您想显示没有SKU的产品?@BrianDeMilia是-可以有两个SKU具有相同的颜色。不过我不想重复,因此在原始的wm_concat中使用了独特的颜色名称。@Davidaber谢谢-让我来探讨一下Listag和下面的解决方案。我很快会回复您。如果这是一个旧的查询(可以追溯到10g),那么使用WM_CONCAT()
是可以理解的。只是用它前进是没有意义的。
select p.product_id,
listagg(s.color_id, ',') within group(order by s.color_id) as colorids,
listagg(s.color_name, ',') within group(order by s.color_id) as colornames
from product p
left join (select distinct product_id, color_id, color_name from sku) s
on p.product_id = s.product_id
group by p.product_id
select product_id,
listagg(color_id,',') within group(order by color_names) as color_ids,
listagg(color_names,',') within group (order by color_names) color_names
from sku
group by product_id;