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

时间:2016-04-14 06:01:12

标签: sql oracle date-arithmetic

我有一个查询,它给出了过去三个月的销售价值。我希望在一个查询中获取所有三个月的数据,而不是三个不同的查询。如果我给'Mar-2016',它应该显示我最近三个月的数据2016年2月,2016年1月和2015年12月。

请帮我解决这个问题。

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 

1 个答案:

答案 0 :(得分:0)

据我所知,在union-ed子查询中唯一不同的是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值比范围内的月数小1:所以2限制了三个月的范围。

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

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

"如果我给'2016年3月'它应该显示我最近3个月的数据2016年2月,2016年1月和2015年12月。"

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

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)的内容。