如何选择和分组已经与Over()分组的查询? - 甲骨文

时间:2014-09-23 10:09:18

标签: sql oracle group-by oracle10g

我试图改进以下查询:

    SELECT TID, INSERTDATE, TNAME, TSURNAME, TDATE1, TDATE2, TDATE3 FROM
    (SELECT T1.TID,T2.INSERTDATE, T1.TNAME, T1.TSURNAME,  T2.TDATE1, T2.TDATE2, T2.TDATE3, ROW_NUMBER() OVER (PARTITION BY T1.TID ORDER BY T2.INSERTDATE DESC) AS RN
FROM MEMBER T1 INNER JOIN MEMBERPROMOTION T2 ON T1.TID=T2.TID WHERE SOME CLAUSES AND
(TDATE1 >= TO_TIMESTAMP('15/07/2014', 'DD/MM/YYYY HH24:MI:SS') AND TDATE1 <= TO_TIMESTAMP('14/08/2014', 'DD/MM/YYYY HH24:MI:SS')) OR 
(TDATE2 >= TO_TIMESTAMP('15/07/2014', 'DD/MM/YYYY HH24:MI:SS') AND TDATE2 <= TO_TIMESTAMP('14/08/2014', 'DD/MM/YYYY HH24:MI:SS')) OR
(TDATE3 >= TO_TIMESTAMP('15/07/2014', 'DD/MM/YYYY HH24:MI:SS') AND TDATE3 <= TO_TIMESTAMP('14/08/2014', 'DD/MM/YYYY HH24:MI:SS'))) 
 ORDERED WHERE RN = 1;

MEMBER

  TID  TNAME   TSURNAME
-------------------------------
   1    BLA   BLABLA    
   2    BL    BLBL    

MEMBERPROMOTIONS

  MPID  TID  INSERTDATE     TDATE1       TDATE2       TDATE3
--------------------------------------------------------
   1     1   11/06/2012   19/07/2013    19/07/2013   19/07/2013
   2     1   05/08/2013   19/07/2014    19/07/2014   19/07/2014 
   3     2   05/08/2013   02/08/2014    21/07/2014   02/08/2014 

预期结果

  TID  INSERTDATE     TDATE1       TDATE2       TDATE3
--------------------------------------------------------
   1   05/08/2013   19/07/2014    19/07/2014   19/07/2014 
   2   05/08/2013   02/08/2014    21/07/2014   02/08/2014 
   2   05/08/2013   02/08/2014    21/07/2014   02/08/2014 

MEMBER表有成员信息,它与TID列上的MEMBERPROMOTIONS表有关系。

如你所见;我有日期输入,我在输入日期之间选择至少一个日期(date1,date2,date3)。我只想要max(INSERTDATE)行,所以我使用了OVER()。

这是我想要完成的事情:

如果TDATE1,TDATE2和TDATE3相同,我想要单行返回,否则我期望多行。关键是我想根据TDATE1,TDATE2和TDATE3进行分组。

1 个答案:

答案 0 :(得分:0)

我认为你正在寻找一个将三个TDATEx列转换成行的插件;然后将每个与你的日期范围进行比较。您已将此标记为10g,因此11g unpivot运算符不可用,因此需要以旧方式完成:

SELECT MP.MPID, MP.TID, MP.INSERTDATE, T.RN AS TDATE_NUM,
  CASE T.RN
    WHEN 1 THEN MP.TDATE1
    WHEN 2 THEN MP.TDATE2
    WHEN 3 THEN MP.TDATE3
  END AS TDATE
FROM (SELECT LEVEL AS RN FROM DUAL CONNECT BY LEVEL <= 3) T
CROSS JOIN MEMBERPROMOTION MP
ORDER BY MP.MPID, RN;

这给了你:

      MPID        TID INSERTDATE  TDATE_NUM TDATE    
---------- ---------- ---------- ---------- ----------
         1          1 11/06/2012          1 19/07/2013 
         1          1 11/06/2012          2 19/07/2013 
         1          1 11/06/2012          3 19/07/2013 
         2          1 05/08/2013          1 19/07/2014 
         2          1 05/08/2013          2 19/07/2014 
         2          1 05/08/2013          3 19/07/2014 
         3          2 05/08/2013          1 02/08/2014 
         3          2 05/08/2013          2 21/07/2014 
         3          2 05/08/2013          3 02/08/2014 

使用它而不是原始表:

SELECT TID, MAX(INSERTDATE), TNAME, TSURNAME, TDATE
FROM (
  SELECT M.TID, MP.INSERTDATE, M.TNAME, M.TSURNAME, MP.TDATE_NUM, MP.TDATE
  FROM MEMBER M
  INNER JOIN (
    SELECT MP.MPID, MP.TID, MP.INSERTDATE, T.RN AS TDATE_NUM,
      CASE T.RN
        WHEN 1 THEN MP.TDATE1
        WHEN 2 THEN MP.TDATE2
        WHEN 3 THEN MP.TDATE3
      END AS TDATE
    FROM (SELECT LEVEL AS RN FROM DUAL CONNECT BY LEVEL <= 3) T
    CROSS JOIN MEMBERPROMOTION MP
  ) MP
  ON MP.TID=M.TID
  WHERE -- SOME CLAUSES AND
    MP.TDATE >= TO_TIMESTAMP('15/07/2014', 'DD/MM/YYYY HH24:MI:SS')
  AND MP.TDATE <= TO_TIMESTAMP('14/08/2014', 'DD/MM/YYYY HH24:MI:SS')
)
GROUP BY TID, TNAME, TSURNAME, TDATE;

给出:

       TID INSERTDATE TNAME      TSURNAME    TDATE_NUM TDATE    
---------- ---------- ---------- ---------- ---------- ----------
         1 05/08/2013 BLA        BLABLA              1 19/07/2014 
         1 05/08/2013 BLA        BLABLA              2 19/07/2014 
         1 05/08/2013 BLA        BLABLA              3 19/07/2014 
         2 05/08/2013 BL         BLBL                1 02/08/2014 
         2 05/08/2013 BL         BLBL                2 21/07/2014 
         2 05/08/2013 BL         BLBL                3 02/08/2014 

然后那可能是你内心的疑问;并且您可以将分组应用于该结果集:

SELECT TID, MAX(INSERTDATE) AS INSERTDATE, TNAME, TSURNAME, TDATE
FROM (
  SELECT M.TID, MP.INSERTDATE, M.TNAME, M.TSURNAME, MP.TDATE_NUM, MP.TDATE
  FROM MEMBER M
  INNER JOIN (
    SELECT MP.MPID, MP.TID, MP.INSERTDATE, T.RN AS TDATE_NUM,
      CASE T.RN
        WHEN 1 THEN MP.TDATE1
        WHEN 2 THEN MP.TDATE2
        WHEN 3 THEN MP.TDATE3
      END AS TDATE
    FROM (SELECT LEVEL AS RN FROM DUAL CONNECT BY LEVEL <= 3) T
    CROSS JOIN MEMBERPROMOTION MP
  ) MP
  ON MP.TID=M.TID
  WHERE -- SOME CLAUSES AND
    MP.TDATE >= TO_TIMESTAMP('15/07/2014', 'DD/MM/YYYY HH24:MI:SS')
  AND MP.TDATE <= TO_TIMESTAMP('14/08/2014', 'DD/MM/YYYY HH24:MI:SS')
)
GROUP BY TID, TNAME, TSURNAME, TDATE
ORDER BY TID, INSERTDATE, TDATE;

,并提供:

       TID INSERTDATE TNAME      TSURNAME   TDATE    
---------- ---------- ---------- ---------- ----------
         1 05/08/2013 BLA        BLABLA     19/07/2014 
         2 05/08/2013 BL         BLBL       21/07/2014 
         2 05/08/2013 BL         BLBL       02/08/2014 

SQL Fiddle