[英]Oracle distinct listagg with count
I need to display a comma-separated description per table row but I need the list to be distinct and have counts for some of the descriptions available. 我需要在每个表行中显示一个逗号分隔的描述,但我需要使列表与众不同,并且要对一些可用的描述进行计数。
every_description needs_count
---------------------------------
Bred yes
From Vendor yes
Grouped no
Removed yes
Separated no
Weaned yes
So in a day, the description could be something like Bred, Grouped, Weaned
and I have this working now using LISTAGG
and removing the duplicates using the solution mentioned here but I need to add counts for some of the descriptions like 5 Bred, Grouped, 2 Weaned
. 因此,一天之内的描述可能像
Bred, Grouped, Weaned
,现在我可以使用LISTAGG
进行此工作,并使用此处提到的解决方案删除重复项,但是我需要为5 Bred, Grouped, 2 Weaned
。
Here's my current query where I'm stuck: 这是我目前遇到的问题:
WITH cages AS (
SELECT 1234 AS id FROM DUAL
UNION SELECT 5678 AS id FROM DUAL
UNION SELECT 9012 AS id FROM DUAL
UNION SELECT 3456 AS id FROM DUAL
), cage_comments AS (
SELECT 1234 AS cage_id, 'Bred' AS description, TO_DATE('11/14/2017', 'MM/DD/YYYY') AS event_date FROM DUAL
UNION SELECT 5678 AS cage_id, 'Grouped' AS description, TO_DATE('11/14/2017', 'MM/DD/YYYY') AS event_date FROM DUAL
UNION SELECT 9012 AS cage_id, 'Weaned' AS description, TO_DATE('11/14/2017', 'MM/DD/YYYY') AS event_date FROM DUAL
UNION SELECT 3456 AS cage_id, 'Weaned' AS description, TO_DATE('11/14/2017', 'MM/DD/YYYY') AS event_date FROM DUAL
UNION SELECT 3456 AS cage_id, 'Bred' AS description, TO_DATE('11/02/2017', 'MM/DD/YYYY') AS event_date FROM DUAL
UNION SELECT 3456 AS cage_id, 'Grouped' AS description, TO_DATE('11/14/2017', 'MM/DD/YYYY') AS event_date FROM DUAL
), calendar AS (
SELECT dt
FROM (
SELECT TRUNC(LAST_DAY(TO_DATE(&month || '/01/' || &year, 'MM/DD/YYYY')) - ROWNUM + 1) dt
FROM DUAL CONNECT BY ROWNUM <= 31
)
WHERE dt >= TRUNC(TO_DATE(&month || '/01/' || &year, 'MM/DD/YYYY'), 'MM')
ORDER BY dt ASC
)
SELECT
cal.dt,
(
SELECT
CASE
WHEN COUNT(cc.cage_id) > 0 THEN RTRIM(
REGEXP_REPLACE(
(LISTAGG(cc.description, ',') WITHIN GROUP (ORDER BY cc.description)),
'([^,]*)(,\1)+($|,)',
'\1\3'
),
','
)
ELSE NULL
END
FROM cages c
LEFT JOIN cage_comments cc ON cc.cage_id = c.id
WHERE cc.event_date = cal.dt
) AS description
FROM calendar cal
ORDER BY cal.dt
In short - I'm just having difficulties adding the COUNT
for some of the descriptions for that day. 简而言之-我很难为当天的某些说明添加
COUNT
。 In the case above I would like to say 1 Bred
for November 2, 2017
and 1 Bred, Grouped, 2 Weaned
for November 14, 2017
. 在上述情况下我想说的
1 Bred
为November 2, 2017
和1 Bred, Grouped, 2 Weaned
为November 14, 2017
。
Currently you are aggregating all the descriptions (without DISTINCT) and then you remove the duplicate descriptions with a regular expression replace. 当前,您正在汇总所有描述(不使用DISTINCT),然后使用正则表达式replace删除重复的描述。 This is very inefficient - it would be better to select distinct and then apply LISTAGG.
这是非常低效的-选择不重复然后应用LISTAGG会更好。
This becomes even more important if you need to add the count. 如果您需要添加计数,这将变得更加重要。 Take the result of your join and GROUP BY description.
获取您的加入和GROUP BY描述的结果。 (In particular, this will take care of DISTINCT).
(特别是,这将处理DISTINCT)。 In the SELECT for this aggregate step, include the count.
在此聚合步骤的“选择”中,包括计数。 Then join the result to the additional table at the top of your question, and re-write the argument to LISTAGG to include a CASE expression, equal to the count (and a space) when the
needs_count
value is 'yes'
. 然后将结果连接到问题顶部的其他表中,并将参数重写为LISTAGG以包括CASE表达式,该表达式等于
needs_count
值为'yes'
时的计数(和空格)。
You could use: 您可以使用:
SELECT
cal.dt,
(
SELECT LISTAGG(CASE WHEN COUNT(*)=1 THEN ''
ELSE CAST(COUNT(*) AS VARCHAR2(10)) || ' ' END || description, ', ')
WITHIN GROUP (ORDER BY description)
FROM cages c
LEFT JOIN cage_comments cc ON cc.cage_id = c.id
WHERE cc.event_date = cal.dt
GROUP BY cc.event_date, cc.description
) AS description
FROM calendar cal
ORDER BY cal.dt;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.