根据日期范围参数

时间:2015-04-23 17:30:22

标签: sql oracle calculated-columns

我是SQL的新手。我目前正在开发 Oracle数据库,我创建了一个报告,根据日期范围参数提取数据。

代码如下:

SELECT 
  DISTINCT C.CUSTOMER_CODE
, MS.SALESMAN_NAME
, SUM(C.REVENUE_AMT) Rev_Amt


FROM 
    C_REVENUE_ANALYSIS C
  , M_CUSTOMER_H MC
  , M_SALESMAN MS


WHERE C.COMPANY_CODE = 'W1'
  AND C.CUSTOMER_CODE = MC.CUSTOMER_CODE
  AND MC.SALESMAN_CODE = MS.SALESMAN_CODE
  AND trunc(C.REVENUE_DATE) between to_date(<STARTDATE>,'YYYYMMDD') and to_date(<ENDDATE>,'YYYYMMDD')
  AND MS.COMPANY_CODE = '00'

GROUP BY C.CUSTOMER_CODE, MS.SALESMAN_NAME

ORDER BY C.CUSTOMER_CODE, MS.SALESMAN_NAME

日期范围从1月1日到4月30日的结果报告是:

+-----------+--------------+--------------+
|Customer   |Salesman Name |Revenue Amount|
+-----------+--------------+--------------+
|Customer 1 |Salesman 1    |       5000.00|
+-----------+--------------+--------------+
|Customer 2 |Salesman 1    |       8000.00|
+-----------+--------------+--------------+
|Customer 3 |Salesman 2    |        300.00|
+-----------+--------------+--------------+
|Customer 4 |Salesman 3    |        600.00|
+-----------+--------------+--------------+
|Customer 5 |Salesman 3    |       5000.00|
+-----------+--------------+--------------+
|Customer 6 |Salesman 3    |       8000.00|
+-----------+--------------+--------------+
|Customer 7 |Salesman 4    |       9000.00|
+-----------+--------------+--------------+
|Customer 8 |Salesman 5    |       2000.00|
+-----------+--------------+--------------+
|Customer 9 |Salesman 6    |       1000.00|
+-----------+--------------+--------------+
|Customer10 |Salesman 6    |       5000.00|
+-----------+--------------+--------------+
|Customer11 |Salesman 7    |       6000.00|
+-----------+--------------+--------------+
|Customer12 |Salesman 8    |       8000.00|
+-----------+--------------+--------------+

现在,我需要你的帮助。我需要在1月到4月之间显示每个销售员每个月的收入分配。

所以我希望结果如下:

+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer   |Salesman Name |Rev for Jan|Rev for Feb|Rev for Mar|Rev for Apr|Total Rev Amt|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 1 |Salesman 1    |    1000.00|    1000.00|    1000.00|    2000.00|      5000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 2 |Salesman 1    |    2000.00|    2000.00|    2000.00|    2000.00|      8000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 3 |Salesman 2    |     100.00|       0.00|     100.00|     100.00|       300.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 4 |Salesman 3    |     100.00|     200.00|     100.00|     200.00|       600.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 5 |Salesman 3    |    1000.00|    2000.00|    1000.00|    1000.00|      5000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 6 |Salesman 3    |    1000.00|    2000.00|    1000.00|    4000.00|      8000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 7 |Salesman 4    |    2000.00|    2000.00|    3000.00|    2000.00|      9000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 8 |Salesman 5    |     500.00|     400.00|     500.00|     600.00|      2000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer 9 |Salesman 6    |     200.00|     200.00|     200.00|     400.00|      1000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer10 |Salesman 6    |    1000.00|    1000.00|    2000.00|    1000.00|      5000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer11 |Salesman 7    |    2000.00|    2000.00|    1000.00|    1000.00|      6000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+
|Customer12 |Salesman 8    |    2000.00|    2000.00|    2000.00|    2000.00|      8000.00|
+-----------+--------------+-----------+-----------+-----------+-----------+-------------+

不幸的是,由于我是新手,我无权创建存储过程以定期调用此数据。所以我可能要编写冗余代码。

但问题是,代码是什么才能分解每个销售员每月的收入?

此外,列数因日期范围而异。例如;选择1月到4月时,我会获得4列收入加1列总收入。如果选择去年10月到今年的4月份,我会获得7列收入加1列总收入。

请有人帮助新手渴望学习和证明自己吗?非常感谢你的帮助。非常感谢。

编辑:

经过一番劝说后,我的经理同意提交我的存储过程以供批准,如果获得批准,则会创建。

如果我确实要创建存储过程,那么获得所需结果的代码是什么?

提前致谢。

4 个答案:

答案 0 :(得分:0)

查看数据透视功能http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html

丑陋的部分是你必须提前知道旋转的列(在你的情况下,选择范围内的月份)。一个潜在的解决方案是使用PLSQL创建动态SQL语句,但您可能没有适当的权限来执行它。您在帖子中提到您无法创建程序(我假设您没有获得CREATE PROCEDURE授权),但不确定这是否是您唯一遗失的资助。

答案 1 :(得分:0)

案例陈述可以在总和中起作用,类似于Pivot陈述。

SELECT 
  DISTINCT C.CUSTOMER_CODE
, MS.SALESMAN_NAME
, SUM(C.REVENUE_AMT) Rev_Amt
,CASE WHEN 
    trunc(C.REVENUE_DATE) between to_date('1 jan 2014','YYYYMMDD') and to_date('31 jan 2014','YYYYMMDD') 
    THEN SUM(C.REVENUE_AMT)
    ELSE 0
 END AS Revenue_Jan_2014

FROM 
    C_REVENUE_ANALYSIS C
  , M_CUSTOMER_H MC
  , M_SALESMAN MS


WHERE C.COMPANY_CODE = 'W1'
  AND C.CUSTOMER_CODE = MC.CUSTOMER_CODE
  AND MC.SALESMAN_CODE = MS.SALESMAN_CODE
  AND trunc(C.REVENUE_DATE) between to_date(<STARTDATE>,'YYYYMMDD') and to_date(<ENDDATE>,'YYYYMMDD')
  AND MS.COMPANY_CODE = '00'

GROUP BY C.CUSTOMER_CODE, MS.SALESMAN_NAME

ORDER BY C.CUSTOMER_CODE, MS.SALESMAN_NAME

但是,正如xionutz2k的回答一样,这也需要知道具体的列。

您可以开始使用Dynamics SQL,但这可能会变得很丑陋。以下是使用Dynamic SQL的参考链接。

Dynamic SQL to generate column names?

答案 2 :(得分:0)

另一种解决方案:

select a.cust, a.salesman, 
    (select sum(b.revenue) from rev b 
    where a.cust=b.cust and a.salesman=b.salesman and
    tr_date between to_date('1 jan 2014','YYYYMMDD') and to_date('31 jan 2014')) Jan_Rev,
    (select sum(c.revenue) from rev c
    where a.cust=c.cust and a.salesman=c.salesman and
    tr_date between to_date('1 feb 2014','YYYYMMDD') and to_date('28 feb 2014')) feb_Rev,
    (select sum(d.revenue) from rev d 
    where a.cust=d.cust and a.salesman=d.salesman and
    tr_date between to_date('1 mar 2014','YYYYMMDD') and to_date('31 mar 2014')) mar_Rev
    ... and so on for more months..
from 
    cust_table a
where
  .. add where clause if any ...

答案 3 :(得分:0)

可以使用以下枢轴。通过使用EXTRACT函数将月份从收入日期中拉出,可以将其用于PIVOT并为每个月创建一列。此外,通过使用带有窗口的SUM,您可以获得每个销售员/客户组合的总收入。

需警惕的是,如果您的日期范围跨越多年,则每年的同一个月将被总计在同一列中。

例如:如果您的日期范围是2019年1月1日至2020年1月31日,则将2019年1月和2020年1月相加。

查询

WITH
    d (customer,
       salesman,
       revenue_amount,
       revenue_date)
    AS
        (SELECT 'Customer 1', 'Salesman 1', 20.00, TO_DATE ('1-JAN-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 1', 'Salesman 1', 30.00, TO_DATE ('8-JAN-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 1', 'Salesman 1', 30.00, TO_DATE ('21-APR-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 1', 'Salesman 1', 57.00, TO_DATE ('12-JUN-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 1', 'Salesman 1', 76.00, TO_DATE ('1-OCT-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 1', 'Salesman 1', 57.00, TO_DATE ('17-MAR-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 2', 'Salesman 1', 12.00, TO_DATE ('3-MAY-2020') FROM DUAL
         UNION ALL
         SELECT 'Customer 3', 'Salesman 2', 300.00, TO_DATE ('5-APR-2020') FROM DUAL)
  SELECT customer,
         salesman,
         NVL (jan, 0)     AS rev_for_jan,
         NVL (feb, 0)     AS rev_for_feb,
         NVL (mar, 0)     AS rev_for_mar,
         NVL (apr, 0)     AS rev_for_apr,
         NVL (may, 0)     AS rev_for_may,
         NVL (jun, 0)     AS rev_for_jun,
         NVL (jul, 0)     AS rev_for_jul,
         NVL (aug, 0)     AS rev_for_aug,
         NVL (sep, 0)     AS rev_for_sep,
         NVL (oct, 0)     AS rev_for_oct,
         NVL (nov, 0)     AS rev_for_nov,
         NVL (dec, 0)     AS rev_for_dec,
         total_revenue
    FROM (SELECT d.customer,
                 d.salesman,
                 d.revenue_amount,
                 EXTRACT (MONTH FROM d.revenue_date)                                 AS revenue_month,
                 SUM (revenue_amount) OVER (PARTITION BY d.customer, d.salesman)     AS total_revenue
            FROM d
           WHERE revenue_date BETWEEN TO_DATE ('1-JAN-2020', 'DD-MON-YYYY')
                                  AND TO_DATE ('30-APR-2020', 'DD-MON-YYYY'))
         PIVOT (SUM (revenue_amount)
               FOR revenue_month
               IN (1 AS jan,
                  2 AS feb,
                  3 AS mar,
                  4 AS apr,
                  5 AS may,
                  6 AS jun,
                  7 AS jul,
                  8 AS aug,
                  9 AS sep,
                  10 AS oct,
                  11 AS nov,
                  12 AS dec))
ORDER BY customer, salesman;

结果

     CUSTOMER      SALESMAN    REV_FOR_JAN    REV_FOR_FEB    REV_FOR_MAR    REV_FOR_APR    REV_FOR_MAY    REV_FOR_JUN    REV_FOR_JUL    REV_FOR_AUG    REV_FOR_SEP    REV_FOR_OCT    REV_FOR_NOV    REV_FOR_DEC    TOTAL_REVENUE
_____________ _____________ ______________ ______________ ______________ ______________ ______________ ______________ ______________ ______________ ______________ ______________ ______________ ______________ ________________
Customer 1    Salesman 1                50              0             57             30              0              0              0              0              0              0              0              0              137
Customer 3    Salesman 2                 0              0              0            300              0              0              0              0              0              0              0              0              300