使用1表的值在SUM中编写子查询

时间:2017-07-26 02:00:50

标签: sql oracle

现在我有一张桌子,我正在尝试计算每一本书_过去一年中每天过去100天的总销售额。

book_id location seller daily_sales order_day
 ABC      1        XYZ   100         2017-05-05
 ABC      1        XYZ   120         2017-05-07
 ABC      1        XYZ   40          2017-02-10
 .
 .
 .

所以我在结果中期待的是:

book_id order_day sum
 ABC    2017-05-05 100+40
 ABC    2017-05-07 100+120+40
 ABC    2017-02-10 40

为此,我写了一个这样的查询:

select book_id, to_char(order_day), 
    SUM(case when order_day between order_day -100 and order_day then daily_sales else 0 end) sum
    FROM bookDetailsTable
    where location = 1 AND ORDER_DAY BETWEEN TO_DATE('20170725','YYYYMMDD') - 359 AND TO_DATE('20170725','YYYYMMDD')
    group by seller, book_id, order_day 

我想我做错了,我应该在SUM语句中编写一个select语句来选择过去100天的数据。

2 个答案:

答案 0 :(得分:2)

你应该用这个

得到结果
select  A.book_id, 
        A.order_day,
        (   select sum(b.daily_sales) 
            from bookDetailsTable b 
            where A.book_id = B.book_id 
            and B.order_day between A.order_day -100 and A.order_day
        )
from bookDetailsTable A
where A.order_day between ADD_MONTHS(trunc(sysdate),-12) and trunc(sysdate)

如果您了解查询的原则,则应该可以添加其他限制,例如sellerlocation

答案 1 :(得分:1)

这是使用分析函数,特别是SUM()分析函数以及窗口子句的完美案例:

WITH bookdetailstable AS (SELECT 'ABC' book_id, 1 LOCATION, 'XYZ' seller, 100 daily_sales, to_date('05/05/2016', 'dd/mm/yyyy') order_day FROM dual UNION ALL
                          SELECT 'ABC' book_id, 1 LOCATION, 'XYZ' seller, 120 daily_sales, to_date('07/05/2016', 'dd/mm/yyyy') order_day FROM dual UNION ALL
                          SELECT 'ABC' book_id, 1 LOCATION, 'XYZ' seller, 40 daily_sales, to_date('10/02/2016', 'dd/mm/yyyy') order_day FROM dual UNION ALL
                          SELECT 'ABC' book_id, 1 LOCATION, 'XYZ' seller, 600 daily_sales, to_date('10/02/2017', 'dd/mm/yyyy') order_day FROM dual)
SELECT book_id,
       to_char(order_day, 'yyyy-mm-dd') order_day,
       total_sales_last_100_days
FROM   (SELECT book_id,
               order_day,
               SUM(daily_sales) OVER (PARTITION BY book_id ORDER BY order_day
                                      RANGE BETWEEN 100 PRECEDING AND CURRENT ROW) total_sales_last_100_days
        FROM   bookdetailstable
        where  order_day >= add_months(trunc(sysdate) - 100, -12))
where  order_day >= add_months(trunc(SYSDATE), -12);

BOOK_ID ORDER_DAY  TOTAL_SALES_LAST_100_DAYS
------- ---------- -------------------------
ABC     2016-02-10                        40
ABC     2016-05-05                       140
ABC     2016-05-07                       260
ABC     2017-02-10                       600

这简单地说得到每个book_id的daily_sales的总和(你可以认为partition by子句与group by子句类似 - 它只是定义了函数适用的行组)按order_day排序,查看前面的100行和当前行。

如果您需要根据位置(以及卖家和......)计算出特定book_ids的累计金额,那么您需要在partition by子句中包含额外的分组列。

由于您希望将结果限制为过去的一年,假设您希望第一行也返回过去100天的计数,而不是从当天开始,则需要包含100天之前的结果。一年前。然后,将行限制为您感兴趣的年份数据。

这是因为分析函数在被where子句过滤后跨数据工作,所以如果你想要包含当前where子句之外的数据,你将不得不寻找一种方法来包含那些行和然后再进行额外的过滤。