如何在单个查询中获取最近三个月的数据
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)
的作用。
我有一个查询,它给出了最近三个月的销售额。我想在单个查询中获取所有三个月的数据,而不是三个不同的查询。如果我给 '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)
的作用。