我需要为每个表行显示逗号分隔的描述,但我需要列表是不同的,并且对某些可用的描述有计数。
every_description needs_count
---------------------------------
Bred yes
From Vendor yes
Grouped no
Removed yes
Separated no
Weaned yes
所以在一天之内,描述可能类似于Bred, Grouped, Weaned
,我现在正在使用LISTAGG
并使用提到的here解决方案删除重复项,但我需要添加计数对于某些描述,例如5 Bred, Grouped, 2 Weaned
。
这是我当前查询的地方:
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
简而言之 - 我在为当天的某些描述添加COUNT
时遇到了困难。在上面的例子中,我想对1 Bred
说November 2, 2017
,为1 Bred, Grouped, 2 Weaned
说November 14, 2017
。
答案 0 :(得分:1)
目前您正在聚合所有描述(没有DISTINCT),然后使用正则表达式替换删除重复描述。这是非常低效的 - 选择distinct然后应用LISTAGG会更好。
如果您需要添加计数,这就变得更加重要。获取您的加入和GROUP BY描述的结果。 (特别是,这将照顾DISTINCT)。在SELECT for this aggregate步骤中,包括计数。然后将结果连接到问题顶部的附加表,并将参数重新写入LISTAGG以包含CASE表达式,等于needs_count
值为{{1时的计数(和空格) }}
答案 1 :(得分:1)
您可以使用:
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;
<强> DBFiddle Demo 强>