是否可以通过listagg对值进行排序

时间:2013-07-03 03:07:43

标签: oracle oracle11g

是否可以不在listagg函数中使用order by子句?我应该这样做以保持值的排序。顺便说一下,我正在使用oracle 11g。以下是我正在使用的查询:

SELECT 
      wipData."Transaction Type"
      ,wipData."Details"
      ,wipData."Values"
      ,NULL
      ,wipdata.containerid
      ,wipdata.specid
      ,wipdata.wiptrackinggroupkeyid
      ,wipdata.wiplothistoryid
      ,NULL wipdatasetupid
      ,wipdata.specname
      ,NULL linkid
FROM
(
    SELECT wipdata.containerid
          ,wipdata.wiplothistoryid
          ,wipdata.wiptrackinggroupkeyid
          ,wipdata.specid  
          ,wipdata.specname
          ,'WIP Data Collection @'|| SUBSTR(wipdata.specname,0,4) AS "Transaction Type"
          ,LISTAGG(wipdata.wipdatanamename ||': ' , 'break') WITHIN GROUP ( ORDER BY wipdata.wipdatanamename) AS "Details" 
          ,LISTAGG(wipdata.wipdatavalue, 'break') WITHIN GROUP ( ORDER BY wipdata.wipdatanamename) AS "Values" 
    FROM
    (
      SELECT c.containerid
            ,wldd.wipdatanamename
            ,wldd.wipdatavalue
            ,wldd.iswaferdata
            ,wl.specname
            ,wl.wiplothistoryid
            ,wl.wiptrackinggroupkeyid
            ,wl.specid
      FROM Container C
      JOIN a_wiplothistory wl ON c.containerid = wl.containerid
      JOIN a_wiplotdetailshistory wld ON wl.wiplothistoryid = wld.wiplothistoryid
      JOIN a_wiplotdetailsdatahistory wldd ON wld.wiplotdetailshistoryid = wldd.wiplotdetailshistoryid
      WHERE c.containername = :lotID AND wldd.iswaferdata = 0 AND wldd.servicename <> 'AdHocWIPData'
    ) wipdata
    GROUP BY wipdata.containerid
          ,wipdata.wiplothistoryid
          ,wipdata.wiptrackinggroupkeyid
          ,wipdata.specid  
          ,wipdata.specname

) WipData

UNION ALL

SELECT 
      wipData."Transaction Type"
      ,wipData."Details"
      ,wipData."Values"
      ,NULL
      ,wipdata.containerid
      ,wipdata.specid
      ,wipdata.wiptrackinggroupkeyid
      ,wipdata.wiplotid
      ,NULL
      ,wipdata.specname
      ,NULL
FROM
(
SELECT wipdata.containerid
      ,wipdata.wiplotid
      ,wipdata.wiptrackinggroupkeyid
      ,wipdata.specid  
      ,wipdata.specname
      ,'WIP Data Collection @'|| SUBSTR(wipdata.specname,0,4) AS "Transaction Type"
      ,LISTAGG(wipdata.wipdatanamename ||': ' || wipdata.wipdatavalue, 'break') WITHIN GROUP ( ORDER BY wipdata.wipdatanamename) AS "Details" 
      ,LISTAGG(wipdata.wipdatavalue, 'break') WITHIN GROUP ( ORDER BY wipdata.wipdatanamename) AS "Values" 
FROM
(
  SELECT c.containerid
        ,wldd.wipdatanamename
        ,wldd.wipdatavalue
        ,wldd.iswaferdata
        ,wl.specname
        ,wl.wiplotid

        ,wl.wiptrackinggroupkeyid
        ,wl.specid
  FROM Container C
  JOIN a_wiplot wl ON c.containerid = wl.containerid
  JOIN a_wiplotdetails wld ON wl.wiplotid = wld.wiplotid
  JOIN a_wiplotdetailsdata wldd ON wld.wiplotdetailsid = wldd.wiplotdetailsid
  WHERE c.containername = :lotID AND wldd.iswaferdata = 0 AND wldd.servicename <> 'AdHocWIPData'
) wipdata
GROUP BY wipdata.containerid
      ,wipdata.wiplotid
      ,wipdata.wiptrackinggroupkeyid
      ,wipdata.specid  
      ,wipdata.specname

) WipData

谢谢你们。

2 个答案:

答案 0 :(得分:0)

您可以保留值的顺序,但必须在之前定义此顺序。

基于问题UNION ALL查询的第一部分的示例:

SELECT 
      wipData."Transaction Type"
      ,wipData."Details"
      ,wipData."Values"
      ,NULL
      ,wipdata.containerid
      ,wipdata.specid
      ,wipdata.wiptrackinggroupkeyid
      ,wipdata.wiplothistoryid
      ,NULL wipdatasetupid
      ,wipdata.specname
      ,NULL linkid
FROM
(
    SELECT wipdata.containerid
          ,wipdata.wiplothistoryid
          ,wipdata.wiptrackinggroupkeyid
          ,wipdata.specid  
          ,wipdata.specname
          ,'WIP Data Collection @'|| SUBSTR(wipdata.specname,0,4) AS "Transaction Type"
          ,LISTAGG(wipdata.wipdatanamename ||': ' , 'break') 
              --- order by row number of inner query
              WITHIN GROUP ( ORDER BY ordered_row_number) AS "Details" 
          ,LISTAGG(wipdata.wipdatavalue, 'break') 
              --- order by row number of inner query
             WITHIN GROUP ( ORDER BY ordered_row_number) AS "Values" 
    FROM
    (
      SELECT c.containerid
            ,wldd.wipdatanamename
            ,wldd.wipdatavalue
            ,wldd.iswaferdata
            ,wl.specname
            ,wl.wiplothistoryid
            ,wl.wiptrackinggroupkeyid
            ,wl.specid
            ------- store number of the row in defined order ----------------- 
            , rownum as ordered_row_number
            ------------------------------------------------------------------  
      FROM Container C
      JOIN a_wiplothistory wl ON c.containerid = wl.containerid
      JOIN a_wiplotdetailshistory wld ON wl.wiplothistoryid = wld.wiplothistoryid
      JOIN a_wiplotdetailsdatahistory wldd ON wld.wiplotdetailshistoryid = wldd.wiplotdetailshistoryid
      WHERE c.containername = :lotID AND wldd.iswaferdata = 0 AND wldd.servicename <> 'AdHocWIPData'
      ---- !!! Ordering definition mandatory to get predictable results !!! ----
      ORDER BY c.containername, wldd.servicename
      --------------------------------------------------------------------------
    ) wipdata
    GROUP BY wipdata.containerid
          ,wipdata.wiplothistoryid
          ,wipdata.wiptrackinggroupkeyid
          ,wipdata.specid  
          ,wipdata.specname

) WipData

在您的情况下,只需指定

即可获得与上述示例相同的结果
 LISTAGG(...) WITHIN GROUP (ORDER BY c.containername, wldd.servicename)

所以现在需要进行内部查询修改。

如果您不担心listagg()中值的顺序,请使用ORDER BY中的任何常量:

 LISTAGG(...) WITHIN GROUP (ORDER BY 'No order')

我尝试直接在listagg(SQLFiddle)中使用rownum,它适用于简单查询,但也取决于执行计划,因此保留记录顺序无法保证。

<强>更新

使用分析函数row_number()可以实现相同的效果:

SELECT 
      wipData."Transaction Type"
      ,wipData."Details"
      ,wipData."Values"
      ,NULL
      ,wipdata.containerid
      ,wipdata.specid
      ,wipdata.wiptrackinggroupkeyid
      ,wipdata.wiplothistoryid
      ,NULL wipdatasetupid
      ,wipdata.specname
      ,NULL linkid
FROM
(
    SELECT wipdata.containerid
          ,wipdata.wiplothistoryid
          ,wipdata.wiptrackinggroupkeyid
          ,wipdata.specid  
          ,wipdata.specname
          ,'WIP Data Collection @'|| SUBSTR(wipdata.specname,0,4) AS "Transaction Type"
          ,LISTAGG(wipdata.wipdatanamename ||': ' , 'break') 
              --- order by row number of inner query
              WITHIN GROUP ( ORDER BY ordered_row_number) AS "Details" 
          ,LISTAGG(wipdata.wipdatavalue, 'break') 
              --- order by row number of inner query
             WITHIN GROUP ( ORDER BY ordered_row_number) AS "Values" 
    FROM
    (
      SELECT c.containerid
            ,wldd.wipdatanamename
            ,wldd.wipdatavalue
            ,wldd.iswaferdata
            ,wl.specname
            ,wl.wiplothistoryid
            ,wl.wiptrackinggroupkeyid
            ,wl.specid
            ------- store number of the row in defined order ----------------- 
            , row_number() over (order by c.containername, wldd.servicename) as ordered_row_number
            ------------------------------------------------------------------  
      FROM Container C
      JOIN a_wiplothistory wl ON c.containerid = wl.containerid
      JOIN a_wiplotdetailshistory wld ON wl.wiplothistoryid = wld.wiplothistoryid
      JOIN a_wiplotdetailsdatahistory wldd ON wld.wiplotdetailshistoryid = wldd.wiplotdetailshistoryid
      WHERE c.containername = :lotID AND wldd.iswaferdata = 0 AND wldd.servicename <> 'AdHocWIPData'
    ) wipdata
    GROUP BY wipdata.containerid
          ,wipdata.wiplothistoryid
          ,wipdata.wiptrackinggroupkeyid
          ,wipdata.specid  
          ,wipdata.specname

) WipData

答案 1 :(得分:-1)