SQL LISTAGG最小和最大函数问题

时间:2015-05-29 06:32:35

标签: sql oracle oracle11g minmax listagg

需要在list标签内找到最小和最大日期 像这样在一栏Min Date:01/01/2015 / Max Date:01/05/2015

SELECT D.ITEM_ID AS "ItemId",
       C.NAME AS "ItemName",
       D.UOM_ID AS "UomId",
       B.DESCRIPTION AS "Uom",
       sum(D.REQUIRED_QTY) AS "Quantity",
       LISTAGG(A.REASON, ', ') WITHIN GROUP (ORDER BY A.REASON) "ReasonType",
       LISTAGG(D.REQUIRED_DATE, ', ') WITHIN GROUP (ORDER BY D.REQUIRED_DATE) "PoRequiredDate",  
       LISTAGG(D.PO_COMMENT, ', ') WITHIN GROUP (ORDER BY D.PO_COMMENT) "Comment"
FROM BIZZXE_V2_SCH.REASONS A,
     BIZZXE_V2_SCH.UOMS B,
     BIZZXE_V2_SCH.ITEMS C,
     BIZZXE_V2_SCH.PO_REQUEST_ITEMS D,
     BIZZXE_V2_SCH.PO_REQUESTS E
WHERE E.PO_REQUEST_ID=D.PO_REQUEST_ID
  AND D.ITEM_ID=C.ITEM_ID
  AND D.UOM_ID=B.UOM_ID
  AND D.REASON_ID=A.REASON_ID
GROUP BY D.ITEM_ID, C.NAME, D.UOM_ID, B.DESCRIPTION 

需要将Min dt和Max dt添加到一列作为" PoRequiredDate"

 WITH DATA AS(
   SELECT  listagg(REQUIRED_DATE, ',') WITHIN GROUP (ORDER BY REQUIRED_DATE) dt
    FROM PO_REQUEST_ITEMS 
  WHERE PO_REQUEST_ID =16

  )
 SELECT dt,
        SUBSTR(dt, 1, instr(dt, ',', 1, 1)-1) min_dt,
         SUBSTR(dt, instr(dt, ',', -1, 1)+1)   max_dt
  FROM data
  /

2 个答案:

答案 0 :(得分:0)

因此,您希望LISTAGG输出的聚合值具有 MIN MAX 日期。

由于 LISTAGG 将始终具有有序值,因此最小日期将是逗号分隔列表中的第一个元素,并且最大值日期将是每个组中的最后一个元素

所以,你需要使用的是:

  • SUBSTR
  • INSTR

例如,

SQL> WITH DATA AS(
  2  SELECT deptno, listagg(hiredate, ',') WITHIN GROUP (ORDER BY deptno) dt
  3    FROM emp
  4   WHERE deptno <> 30
  5  GROUP BY deptno
  6  )
  7  SELECT deptno,
  8         dt,
  9         SUBSTR(dt, 1, instr(dt, ',', 1, 1)-1) min_dt,
 10         SUBSTR(dt, instr(dt, ',', -1, 1)+1)   max_dt
 11  FROM data
 12  /

    DEPTNO DT                                                      MIN_DT          MAX_DT
---------- ------------------------------------------------------- --------------- ----------
        10 1981-06-09,1981-11-17,1982-01-23                        1981-06-09      1982-01-23
        20 1980-12-17,1981-04-02,1981-12-03,1982-12-09,1983-01-12  1980-12-17      1983-01-12

SQL>

答案 1 :(得分:0)

您可以使用语法“KEEP(DENSE_RANK FIRST / LAST ...)”为您的目的:

   'Min Date: '||min(REQUIRED_DATE) KEEP (DENSE_RANK FIRST ORDER BY REQUIRED_DATE) ||
' / Max Date: '||min(REQUIRED_DATE) KEEP (DENSE_RANK LAST ORDER BY REQUIRED_DATE NULLS FIRST)

主要问题有 FIRST LAST 关键字 - 它们是聚合或分析功能。 KEEP 表示将在表达式中使用FIRST或LAST。 DENSE_RANK 表示数据库将仅使用具有最小(FIRST)或最大(LAST)密集等级的值。密集排名计算基于排序,排序由 ORDER BY 子句设置。

请注意,在您的情况下,如果在主表达式中使用MIN或MAX,则无关紧要。这是因为上面描述的函数“KEEP ... DENSE_RANK ... FIRST / LAST”仅将那些已经具有极值的记录传递给聚合函数(MIN / MAX)。