如何在单个查询中获取最近三个月的数据

How to get last three months' data in single query

我有一个查询,它给出了最近三个月的销售额。我想在单个查询中获取所有三个月的数据,而不是三个不同的查询。如果我给 'Mar-2016' 它应该显示最近三个月的数据 Feb-2016、Jan-2016 和 Dec-2015。

请帮我解决这个问题。

SELECT 
    TO_CHAR(A.JOB_DATE , 'MON-YYYY') S_MON , NULL T_MON, 
    TO_CHAR(A.JOB_DATE,'MM-YYYY') MM, C.SECTION_CODE SECTION,  
    B.ITEM_CODE ITEM_CODE, SUM(B.MASTER_QUANTITY) SALES,
    NULL TARGET
FROM 
    TRANSACTION_MASTER A, TRANSACTION_DETAIL B, 
    ITEM_SECTION C, ITEM D
WHERE 
    A.TRANSACTION_NUMBER = B.TRANSACTION_NUMBER
    AND TO_CHAR(ADD_MONTHS(A.JOB_DATE,1), 'MON-YYYY') = 'MAR-2016'
    AND A.TRANSACTION_CODE = B.TRANSACTION_CODE
    AND B.ITEM_CODE  = D.ITEM_CODE
    AND C.SECTION_CODE = D.SECTION_CODE
    AND A.TRANSACTION_CODE IN (2,4)
    AND D.ITEM_STATUS = 'A'
    AND C.SECTION_CODE BETWEEN :ST_CODE AND :END_CODE 
GROUP BY  
    TO_CHAR(A.JOB_DATE, 'MON-YYYY'), TO_CHAR(A.JOB_DATE, 'MM-YYYY'),
    C.SECTION_CODE, B.ITEM_CODE 

UNION

SELECT 
    TO_CHAR(A.JOB_DATE, 'MON-YYYY') S_MON, NULL T_MON,  
    TO_CHAR(A.JOB_DATE, 'MM-YYYY') MM, 
    C.SECTION_CODE SECTION, B.ITEM_CODE ITEM_CODE, 
    SUM(B.MASTER_QUANTITY ) SALES, NULL TARGET
FROM 
    TRANSACTION_MASTER A, TRANSACTION_DETAIL B, 
    ITEM_SECTION C, ITEM D
WHERE 
    A.TRANSACTION_NUMBER = B.TRANSACTION_NUMBER
    AND TO_CHAR(ADD_MONTHS(A.JOB_DATE, 2), 'MON-YYYY')= 'MAR-2016'
  AND A.TRANSACTION_CODE = B.TRANSACTION_CODE
  AND B.ITEM_CODE  = D.ITEM_CODE
  AND C.SECTION_CODE = D.SECTION_CODE
  AND A.TRANSACTION_CODE IN (2,4)
  AND D.ITEM_STATUS = 'A'
  AND C.SECTION_CODE BETWEEN :ST_CODE AND :END_CODE 


  GROUP BY  TO_CHAR(A.JOB_DATE , 'MON-YYYY') , TO_CHAR(A.JOB_DATE,'MM-YYYY') ,C.SECTION_CODE  ,  B.ITEM_CODE 


  UNION  

  SELECT TO_CHAR(A.JOB_DATE , 'MON-YYYY') S_MON , NULL T_MON , TO_CHAR(A.JOB_DATE,'MM-YYYY') MM , 
  C.SECTION_CODE SECTION ,  B.ITEM_CODE ITEM_CODE , SUM(B.MASTER_QUANTITY ) SALES , NULL TARGET

  FROM TRANSACTION_MASTER A  , TRANSACTION_DETAIL B  , ITEM_SECTION C , ITEM D

  WHERE A.TRANSACTION_NUMBER = B.TRANSACTION_NUMBER
  AND  TO_CHAR(ADD_MONTHS(A.JOB_DATE,3),'MON-YYYY') = 'MAR-2016'
  AND A.TRANSACTION_CODE = B.TRANSACTION_CODE
  AND B.ITEM_CODE  = D.ITEM_CODE
  AND C.SECTION_CODE = D.SECTION_CODE
  AND A.TRANSACTION_CODE IN (2,4)
  AND D.ITEM_STATUS = 'A'
  AND C.SECTION_CODE BETWEEN :ST_CODE AND :END_CODE 

   GROUP BY  TO_CHAR(A.JOB_DATE , 'MON-YYYY') , TO_CHAR(A.JOB_DATE,'MM-YYYY') ,C.SECTION_CODE  ,  B.ITEM_CODE 

据我所知,联合子查询中唯一不同的是 WHERE 子句的这一行:

AND TO_CHAR(ADD_MONTHS(A.JOB_DATE,1), 'MON-YYYY') = 'MAR-2016'
                                  ^

您应用的实际逻辑是 (*):

and a.job_date between date '2015-12-01' and date '2016-02-29'

这可以用参数概括为

and a.job_date between :p_start_date and last_day(add_months(:p_start_date,2))

如果日期范围内的月数也是可变的,那么您需要另一个参数。

和a.job_date介于:p_start_date和last_day(add_months(:p_start_date,:p_add_months_int))

p_add_months_int 值比范围内的月数小一:因此 2 限定三个月的范围。

如果您想通过传递结束日期来定义过去三个月的范围,请在 add_months() 调用中使用负数:

and a.job_date between trunc(add_months(:p_end_date,-2)) and last_day(:p_end_date)

" if i give 'Mar-2016' it should display me last 3 months data Feb-2016 , Jan-2016 and Dec-2015."

好的,正因为如此,你想要的是

and a.job_date between add_months(to_date(:p_start_date, 'MON-YYYY'),-3)) 
              and to_date(:p_start_date, 'MON-YYYY'),-1)

(*) 如果您期望日期范围为 2016-01-01 到 2016-03-31,您可能误解了 ADD_MONTHS(A.JOB_DATE,1) 的作用。