簡體   English   中英

帶有計數的Oracle獨特的listagg

[英]Oracle distinct listagg with count

我需要在每個表行中顯示一個逗號分隔的描述,但我需要使列表與眾不同,並且要對一些可用的描述進行計數。

every_description     needs_count
---------------------------------
Bred                          yes
From Vendor                   yes
Grouped                        no
Removed                       yes
Separated                      no
Weaned                        yes

因此,一天之內的描述可能像Bred, Grouped, Weaned ,現在我可以使用LISTAGG進行此工作,並使用此處提到的解決方案刪除重復項但是我需要為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 BredNovember 2, 20171 Bred, Grouped, 2 WeanedNovember 14, 2017

當前,您正在匯總所有描述(不使用DISTINCT),然后使用正則表達式replace刪除重復的描述。 這是非常低效的-選擇不重復然后應用LISTAGG會更好。

如果您需要添加計數,這將變得更加重要。 獲取您的加入和GROUP BY描述的結果。 (特別是,這將處理DISTINCT)。 在此聚合步驟的“選擇”中,包括計數。 然后將結果連接到問題頂部的其他表中,並將參數重寫為LISTAGG以包括CASE表達式,該表達式等於needs_count值為'yes'時的計數(和空格)。

您可以使用:

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演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM