Oracle SQL - 只有在某个条件为真时才可以连接两个表吗?

时间:2013-02-23 15:17:45

标签: sql oracle oracle10g oracle11g

我有一张桌子,我必须与之合作,遗憾的是设计不是很好。该表列出了现有产品 与其他产品相匹配。匹配有两种类型:与主要类别产品匹配以及与替代类别产品匹配。

每当匹配时,该匹配的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时的结果。

2 个答案:

答案 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
/