使用连接和解码在子选择中排序
Order By in subselect using concat and decode
假设我有两个表:
产品
product_id (other fields are of no concern)
斯库
product_id sku_id color_id color_name (other fields such as size but unimportant)
001 11 5 green
001 12 1 black
001 13 3 red
002 21 1 black
002 22 2 yellow
002 23 8 magenta
002 24 9 turquoise
我需要重写一个查询,该查询获取产品 ID 列表,其中包含与该产品关联的所有 colors/color ID 的逗号分隔列表。颜色 ids/names 在两个列表中的顺序必须相同。
期望的输出:
product_id colorIds colorNames
001 1,3,5 black,red,green
002 1,2,8,9 black,yellow,magenta,turquoise
请注意,颜色 ID 顺序的连接列表映射到颜色名称顺序。
当前输出:
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;
我正在考虑在那些子选择中添加 order by 子句,但查询出错,说缺少右括号 - 奇怪的是似乎没有不匹配的括号。欢迎提出任何建议。
编辑 *
上面的查询被高度简化了。实际上,它与十几个其他表连接以获得与产品相关的其他数据列,其中大部分是非聚合数据。解决方案应该在主查询中没有 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
LISTAGG()
可以排序,而 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
不能和listagg
一起使用):
select product_id,
listagg(color_id, ',') within group(order by color_id) as colorids,
listagg(color_name, ',') within group(order by color_id) as colornames
from (select distinct product_id, color_id, color_name from sku)
group by product_id
如果您想显示 product
table and/or 中的列,您希望在 product
table 上显示产品而不是 sku
table 你可以使用:
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;
假设我有两个表:
产品
product_id (other fields are of no concern)
斯库
product_id sku_id color_id color_name (other fields such as size but unimportant)
001 11 5 green
001 12 1 black
001 13 3 red
002 21 1 black
002 22 2 yellow
002 23 8 magenta
002 24 9 turquoise
我需要重写一个查询,该查询获取产品 ID 列表,其中包含与该产品关联的所有 colors/color ID 的逗号分隔列表。颜色 ids/names 在两个列表中的顺序必须相同。
期望的输出:
product_id colorIds colorNames
001 1,3,5 black,red,green
002 1,2,8,9 black,yellow,magenta,turquoise
请注意,颜色 ID 顺序的连接列表映射到颜色名称顺序。
当前输出:
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;
我正在考虑在那些子选择中添加 order by 子句,但查询出错,说缺少右括号 - 奇怪的是似乎没有不匹配的括号。欢迎提出任何建议。
编辑 * 上面的查询被高度简化了。实际上,它与十几个其他表连接以获得与产品相关的其他数据列,其中大部分是非聚合数据。解决方案应该在主查询中没有 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
LISTAGG()
可以排序,而 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
不能和listagg
一起使用):
select product_id,
listagg(color_id, ',') within group(order by color_id) as colorids,
listagg(color_name, ',') within group(order by color_id) as colornames
from (select distinct product_id, color_id, color_name from sku)
group by product_id
如果您想显示 product
table and/or 中的列,您希望在 product
table 上显示产品而不是 sku
table 你可以使用:
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;