listagg 函数失败

Posted

技术标签:

【中文标题】listagg 函数失败【英文标题】:listagg function is failing 【发布时间】:2012-08-02 11:12:52 【问题描述】:

我正在尝试使用 listagg 作为 listagg(select...) 方式,但我想这不可能以我想说的方式。

我有一张度数表。

Degree table:
-----------------------------------------------
| user_id | degree_fi | degree_en | degree_sv |
-----------------------------------------------
| 3601464 | 3700      |  1600     |  2200     |
|  1020   | 100       |  0        |   0       |
| 3600520 |  100      | 1300      |  1400     |
| 3600882 |  0        |   100     |  200      |
| 3600520 |  3200     |   800     |  600      |
| 3600520 |  400      | 3000      |  1500     |
-----------------------------------------------

然后我有另一个表格,上面有这些等级的名称。

codes:
------------------------------
|  degree_code |  degree_text|
------------------------------
|   3700       |  Masters    |
|   100        | Bachelors   |
|   3200       | Doctorate   |
|   400        |  Diploma A  |
|   1600       | High school |
|   1300       | Secondary   |
|   800        | Post doc    |
|   3000       | Training    |
|   2200       | LLB         |
|   1400       | M.Sc        |
|   200        |  B.Sc       |
|   600        | Foreign Dip |
|   1500       | Failure     |
------------------------------

我想要的是这样的:

--------------------------------------------------------------------------------------------------------------------------------------------------------------
 | user_id | degree_fi    | degree_fi_txt                   | degree_en       | degree_en_txt                  |degree_sv        | degree_sv_txt              |
 --------------------------------------------------------------------------------------------------------------------------------------------------------------
 | 3601464 | 3700         | Masters                         | 1600            |  high school                   |  2200           |   LLB                      |
 |  1020   | 100          | Bachelors                       | 0               |                                |   0             |                            |
 | 3600520 | 100,3200,400 | Bachelors, Doctorate, Diploma A | 1300, 800, 3000 |  secondary, post doc, Training | 1400, 600, 1500 | M.Sc, Foreign Dip, Failure | 
 | 3600882 |  0           |                                 | 100             |  Bachelors                     |  200            |   B.Sc                     |
  -------------------------------------------------------------------------------------------------------------------------------------------------------------

我尝试过这样使用 listagg 函数:

SELECT user_id, listagg(degree_fi, ',') within GROUP (ORDER BY degree_fi) degree_fi,
                listagg(SELECT degree_text from codes WHERE degree_code IN (SELECT degree_fi feom degree), ',') within GROUP (ORDER BY degree_text) degree_fi_txt,
                listagg(degree_en, ',') within GROUP (ORDER BY degree_en) degree_en,
                listagg(SELECT degree_text from codes WHERE degree_code IN (SELECT degree_en feom degree), ',') within GROUP (ORDER BY degree_text) degree_en_txt,
                listagg(degree_sv, ',') within GROUP (ORDER BY degree_en) degree_sv
                listagg(SELECT degree_text from codes WHERE degree_code IN (SELECT degree_sv feom degree), ',') within GROUP (ORDER BY degree_text) degree_sv_txt,
FROM  degree GROUP BY user_id

但我正在碰壁。 有什么推荐吗?

提前致谢。

【问题讨论】:

【参考方案1】:

您只需加入codes 表三次,而不是在listagg 中使用select

SELECT user_id,
    listagg(d.degree_fi, ',')
        WITHIN GROUP (ORDER BY d.degree_fi) degree_fi,
    listagg(cf.degree_text, ',')
        WITHIN GROUP (ORDER BY d.degree_fi) degree_fi_txt,
    listagg(d.degree_en, ',')
        WITHIN GROUP (ORDER BY d.degree_en) degree_en,
    listagg(ce.degree_text, ',')
        WITHIN GROUP (ORDER BY d.degree_en) degree_en_txt,
    listagg(d.degree_sv, ',')
        WITHIN GROUP (ORDER BY d.degree_sv) degree_sv,
    listagg(cs.degree_text, ',')
        WITHIN GROUP (ORDER BY d.degree_sv) degree_sv_txt
FROM degree d
LEFT JOIN codes cf on cf.degree_code = d.degree_fi
LEFT JOIN codes ce on ce.degree_code = d.degree_en
LEFT JOIN codes cs on cs.degree_code = d.degree_sv
GROUP BY d.user_id
ORDER BY d.user_id;


   USER_ID DEGREE_FI            DEGREE_FI_TXT                  DEGREE_EN            DEGREE_EN_TXT                  DEGREE_SV            DEGREE_SV_TXT
---------- -------------------- ------------------------------ -------------------- ------------------------------ -------------------- ------------------------------
      1020 100                  Bachelors                      0                                                   0
   3600520 100,400,3200         Bachelors,Diploma A,Doctorate  800,1300,3000        Post doc,Secondary,Training    600,1400,1500        Foreign Dip,M.Sc,Failure
   3600882 0                                                   100                  Bachelors                      200                  B.Sc
   3601464 3700                 Masters                        1600                 High school                    2200                 LLB

我不确定您是否希望 degree_text 值按字母顺序排序,或者与 ID 的顺序匹配;我选择了后者,但如果您想要前者,您可以将 order by 更改为 cf.degree_text 等。

【讨论】:

谢谢亚历克斯,是的,我应该去加入方式:-)

以上是关于listagg 函数失败的主要内容,如果未能解决你的问题,请参考以下文章

LISTAGG 失败,SQLCODE=-440

oracle分析函数listagg

Listagg 函数与 PLSQL 集合

Oracle 列转行函数 Listagg()

用listagg怎么替代这个写法

oracle行转列,列转行函数的使用(listagg,xmlagg)