我有一张桌子,我必须与之合作,遗憾的是设计不是很好。该表列出了现有产品 与其他产品相匹配。匹配有两种类型:与主要类别产品匹配以及与替代类别产品匹配。
每当匹配时,该匹配的ID将填入表格中的相关列,如下面的PRODUCT_MATCH所示。因此,在每个产品行中,PRODUCT_MAIN_CATEGORY_ID或PRODUCT_ALTERNATIVE_CATEGORY_ID中都会指定PRODUCT_ID,但两者都不会。
产品
PRODUCT_ID PRODUCT_CATEGORY PRODUCT_SERIAL_NO
1001 Book XSDAD132
1002 MP3 X348023948
1003 DVD 5234234023948
2003 CD SDRX83489
2002 Video 23423879JJ0
PRODUCT_MATCH
PRODUCT_MATCH_ID, PRODUCT_ID, MAIN_CATEGORY_ID, ALTERNATIVE_CATEGORY_ID, PRODUCT_CATEGORY
1 1001 1002 Book
2 1001 1003 Book
3 1002 1004 Book
4 2002 1002 Video
5 2002 1003 Video
6 2002 1001 Video
7 2002 1002 Video
8 1003 2003 DVD
我必须阅读PRODUCT_MATCH表,这样如果MAIN_CATEGORY_ID上有匹配,我会显示ID,或者如果有ALTERNATIVE_CATEGORY_ID,我必须显示product_id和产品ID的序列号。
我编写了以下查询来显示结果
select product_id,
cast(collect(coalesce(MAIN_CATEGORY_ID,
decode(ALTERNATIVE_CATEGORY_ID,null,null, ALTERNATIVE_CATEGORY_ID || '-' || PRODUCT_CATEGORY))) as myType) as product_matches
from product_match
group by product_id
注意:MyType被定义为varchar(2000)
的表如果查询将不为null,则查询将使用MAIN_CATEGORY_ID,否则它将使用ALTERNATIVE_CATEGORY_ID中的值来构建输出。我想更改此设置,以便只要coalesce函数使用ALTENATIVE_CATEGORY_ID值,它就会显示与PRODUCT编号中的product_serial_no连接的product_id。这将需要与PRODUCT表联接。
基本上我想要实现的输出看起来像这样:
PRODUCT_ID PRODUCT_MATCHES
-----------------------------------
1001 1002,DVD-5234234023948
1002 1004
2002 MP3-X348023948, 1003, 1001, 1002
1003 CD-SDRX83489
我知道我可以简单地加入表格但不是那么简单。问题是如果使用ALTERNATIVE_CATEGORY_ID,我只想使用连接。这意味着简单连接将影响使用MAIN_CATEGORY_ID时的结果。
答案 0 :(得分:4)
select
pm.product_id,
cast(
collect(
coalesce(
pm.MAIN_CATEGORY_ID,
pm.ALTERNATIVE_CATEGORY_ID || '-' || pr.PRODUCT_SERIAL_NO
)
) as myType
) as product_matches
from
product_match pm
left join PRODUCT pr
on pr.PRODUCT_ID = pm.ALTERNATIVE_CATEGORY_ID
group by
pm.product_id
答案 1 :(得分:1)
我认为LISTAGG()或WM_CONCAT()函数是您正在寻找的,因为您写的是表没有嵌套表或集合。 Collect将返回一个集合,主要用于PL / SQL数据类型,而不是简单的表。 LISTAGG()或WM_CONCAT()会将值连接成一个字符串,与示例中的完全相同。 抱歉,我不会添加任何疑问,因为您的输出对我来说非常混乱。我只看到book匹配到product_id = 1001,而不是DVD和其他东西。如果您使用SQL Fiddle创建示例数据或只是创建表和插入,那将是很好的。请在将来这样做。
这对我有用 - emp_test是scott.emp表的精确副本:
ALTERE TABLE emp_test MODIFY ename VARCHAR2(3000);
Update emp_test set ename = rpad(ename, 3000, ' '); Commit;
SELECT deptno
, LISTAGG(TRIM(SUBSTR(ename, 1, 3000)), ',') WITHIN GROUP (ORDER BY ename) AS employees
, count(*) total_emps
FROM emp_test
GROUP BY deptno
/
SELECT deptno
, WM_CONCAT(TRIM(SUBSTR(ename, 1, 3000))) AS employees
, count(*) total_emps
FROM emp_test
GROUP BY deptno
/