【问题标题】:How to use LISTAGG to concatenate from multiple rows?如何使用 LISTAGG 连接多行?
【发布时间】:2018-09-03 09:50:27
【问题描述】:

我在 APEX 5.0 中有这样的报告查询:

WITH inner_table AS
( select distinct 
 i.ID
,i.name
,i.lastname
,case i.gender
   when 'm' then 'Male'
   when 'f' then 'Female'
 end gender
,i.username
,b.name region
,i.address
,i.city city
,i.EMAIL
,r.name as "ROLE"
,ie.address as "region_location"
,case 
   when i.gender='m' THEN 'blue'
   when i.gender='f' THEN '#F6358A'
END i_color
,b.course as COURSE
,si.city UNIVERSITY
,case 
when i.id in (select app_user from scholarship) then 'check'
else 'close'
end as scholarship,
case
when i.id in (select ieur.app_user from ie_user_role ieur where role=4) then 'Admin'
else ''
end admin,
apex_item.checkbox(10, i.id, 'UNCHECKED onclick="highlightRow(this);"') as Del_usr
from  app_users i left join regions b on (i.region=b.id)
left join ie_user_role ur on (i.id = ur.app_user)
left join ie_roles r on(ur.role = r.id)
left join user_house uh on (i.id=uh.app_user)
left join reg_location ie on (uh.house=ie.id)
left join study_list sl on i.id = sl.insan
left join study_institute si on sl.institute = si.id
left join course c on sl.course = c.id
where i.is_active='Y'
order by
i.name,i.lastname,i.username,region, city, i.EMAIL) 
 SELECT * FROM inner_table where (scholarship = :P5_SCHOLARSHIP or :P5_SCHOLARSHIP is null)

我可能会得到这样的结果:

|---------------------|------------------|-------|------------------|
|        Name         |     Lastname     |  ...  |      Course      |
|---------------------|------------------|-------|------------------|
|        Some         |       User       |  ...  | Course1          |
|---------------------|------------------|-------|------------------|
|        Some         |       User       |  ...  | Course2          |
|---------------------|------------------|-------|------------------|

但我想在同一行实现入伍课程,这是以前重复的,所以:

|---------------------|------------------|-------|------------------|
|        Name         |     Lastname     |  ...  |      Course      |
|---------------------|------------------|-------|------------------|
|        Some         |       User       |  ...  | Course1, Course2 |
|---------------------|------------------|-------|------------------|

我尝试使用 LISTAGG,但我没有记下我的尝试,所以很遗憾我现在无法发布。我基本上试过了:

,LISTAGG(b.course, ', ') within group (order by b.course) as COURSE

然后使用 COURSE 添加 GROUP BY,但在这种情况下,整个查询都会受到 GROUP BY 的影响,我必须正确应用其他列,对吗?否则会导致“ORA-00937: not a single-group group function”。我有点迷路了。

我尝试的另一件事是使用与上面相同的 LISTAGG 行的子查询表,并从子查询中获得想要的输出,但随后加入查询的其余部分并没有提供预期的结果。

我想在连接多个表时,我可以在这里为 LISTAGG 使用一些 SQL 帮助。

谢谢。

【问题讨论】:

    标签: sql oracle oracle-apex-5


    【解决方案1】:

    当您使用聚合函数(将多行合并为一个)时,您需要一个 GROUP BY 子句,因此您需要这样的内容:

    SELECT i.username, 
           LISTAGG( c.course, ', ' ) WITHIN GROUP ORDER BY ( c.course )
      FROM app_users i
       ...
      LEFT JOIN course c on sl.course = c.id
     GROUP BY i.username
    

    基本上,任何未聚合的内容都需要包含在GROUP BY 子句中。在一个更简单的查询中尝试它,直到你掌握它的窍门,然后做一个大的。

    【讨论】:

    • 嗨,这解决了我在这里没有正确使用 GROUP BY 的问题,是的。但是,对于整个查询,我没有得到正确的结果。在原始查询中,有 694 条记录,并使用 LISTAGG 其 691。当检查是否有 3 条记录较少,因为它们在同一用户下重复课程时,如预期的那样,我发现相同的课程显示为 4 个用户两次作为 listagg , IE。 'Course1, Course1') - 这是“假”结果。而对于其他 2 个正确显示,同一用户的不同课程以“,”列在一行中。现在很难验证这一点。
    • 您的解决方案是正确的,但现在我发现我在原始查询中可能有一些错误,与 listagg 无关,但这是一个不同的问题...
    【解决方案2】:

    您想要的是具有分析窗口功能的 LISTAGG。然后使用 distinct 删除重复项。这是我的示例结果/数据:http://sqlfiddle.com/#!4/6e8e3f/3

    选择 DISTINCT 名称、姓氏、其他列、 LISTAGG(course, ', ') 组内(按课程排序) OVER (PARTITION BY name, last_name) 作为“课程” FROM 内表;

    【讨论】:

    • 谢谢。您的解决方案和之前回复的解决方案都与我原来的问题相关。在这两种情况下,我都有 4 个用户在 LISTAGG 列中重复课程两次,例如“Course1,Course1”,这 100% 指向原始查询中的错误 SQL,我将进行相应的调查。
    • 现在已投票,早些时候它报告说我可以投票,但直到某些声誉点才公开显示。
    • 其他问题...如何从 LISTAGG 中删除重复项?例如,用户将有 2 个不同的“角色”,因此对于同一用户来说,它们是两行。我也可以(并且应该)将 ROLE 列放在 listagg 下,但它仍然会显示为:“someuser”、“role1、role2”、“course123、course123”,反之亦然 - “someuser”、“role5、role5”, “课程 2,课程 3”。
    猜你喜欢
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多