2015-07-21 43 views
1

我有数据的select count这看起来是这样的:客户ID与多个订单超过滚动日期范围,

order_date phone_number order_number 
---------- ------------ ------------ 
18/03/2015 0912345678 123 
27/03/2015 0912345678 176 
18/03/2015 0973541893 453 
20/03/2015 0565741534 678  
03/04/2015 0565741534 534 

我希望能够编写一个查询,其基于“order_date的”看起来比今天和前9天(或任何其他天数)作为10天滚动窗口,并返回具有多个订单的'phone_number'的计数,以及具有单个订单的'phone_number'的计数,例如

date_from date_to  count_multiple count_single 
---------- ----------- -------------- ------------ 
18/03/2015 27/03/2015 5    15 
19/03/2015 28/03/2015 7    10 
20/03/2015 29/03/2015 6    11 
21/03/2015 30/03/2015 3    17 

我能做的SELECT语句的日期计算的部分,例如:

SELECT DISTINCT order_date - 9 AS date_from, order_date AS date_to 
FROM orders 
WHERE order_date > ((SELECT MIN(order_date) FROM orders) + 9) 
ORDER BY order_date; 

...我能得到我想要的东西,如果我指定精确的参数,例如,对于与多个订单18,2015年3月28日:

SELECT DISTINCT COUNT(*) FROM (
    SELECT phone_number, count(order_number) FROM orders 
    WHERE order_date BETWEEN to_date('18/03/2015', 'dd/mm/yyyy') 
         AND to_date('27/03/2015', 'dd/mm/yyyy') 
    HAVING COUNT(order_number) > 1 
    GROUP BY phone_number 
) multiple_orders 

...与同为单笔订单...

SELECT DISTINCT COUNT(*) FROM (
    SELECT phone_number, count(order_number) FROM orders 
    WHERE order_date BETWEEN to_date('18/03/2015', 'dd/mm/yyyy') 
         AND to_date('27/03/2015', 'dd/mm/yyyy') 
    HAVING COUNT(order_number) = 1 
    GROUP BY phone_number 
) single_orders 

但是,我不明白如何基于前两个日期列在主SELECT子句中包含这些子查询。

我想编写这样的事:

SELECT 
    o.order_date - 9 AS date_from, 
    o.order_date AS date_to, 
    (SELECT DISTINCT COUNT(*) FROM 
    (SELECT x.phone_number, COUNT(x.order_number) FROM orders x 
     WHERE x.order_date BETWEEN (o.order_date - 9) 
          AND o.order_date 
     HAVING COUNT(x.order_number) > 1 
     GROUP BY x.phone_number 
    ) 
) AS Has_Multiple, 
    (SELECT DISTINCT COUNT(*) FROM 
    (SELECT x.phone_number, COUNT(x.order_number) FROM orders x 
     WHERE x.order_date BETWEEN (o.order_date - 9) 
          AND o.order_date 
     HAVING COUNT(x.order_number) = 1 
     GROUP BY x.phone_number 
    ) 
) AS Has_Single 
FROM orders o 
WHERE o.order_date > ((SELECT MIN(order_date) FROM orders) + 9) 
ORDER BY o.order_date; 

当然,上述方法不工作,但我真正追求的是让每个计数的列3的能力并且4根据第1列和第2列(1从2计算)。

当前的错误是:

ORA-00904: "O"."ORDER_DATE": invalid identifier 

注意,如果我不包括在SELECT语句中的子查询我没有得到任何错误。所以看起来我没有正确地做子查询,因为主要查询不能在嵌套子查询中“查看”:(

我已经通过在这里搜索和在Google上找到了所有单个组件......但是我可以'不像是会它们结合起来......尤其是这种“滚动日期窗”的概念。

任何帮助,非常感谢!

+0

你的意思是说,当你的子查询包含到主查询中时,它不起作用?但是,发生了什么事。对我而言,你的查询似乎正在工作。 – Ravi

+0

如果您收到任何错误,则包括其他内容,包括预期输出和当前输出。 – Ravi

+0

谢谢@jWeaver!我现在将包括错误,并在查询中调整错字(我不得不'清理'这些错误,因为这些错误是基于公司数据的) – Ross

回答

1

我想你可以通过使用分析功能与适当的开窗条款达成你的目标。由于您没有提供与您的预期输出数据相匹配的示例输入数据,但我必须提供自己的 - 我只能假设我已经掌握了正确的逻辑;但是您必须重新检查它。风从9天到3天(好吧,从技术上讲,我想这是从10到4天,但是谁在计数?! * {;-))

with sample_data as (select 1 id, 1 num, trunc(sysdate, 'mm') + 1 dt from dual union all 
        select 2 id, 2 num, trunc(sysdate, 'mm') + 1 dt from dual union all 
        select 3 id, 3 num, trunc(sysdate, 'mm') + 1 dt from dual union all 
        select 4 id, 1 num, trunc(sysdate, 'mm') + 2 dt from dual union all 
        select 5 id, 2 num, trunc(sysdate, 'mm') + 2 dt from dual union all 
        select 6 id, 4 num, trunc(sysdate, 'mm') + 2 dt from dual union all 
        select 7 id, 4 num, trunc(sysdate, 'mm') + 3 dt from dual union all 
        select 8 id, 1 num, trunc(sysdate, 'mm') + 3 dt from dual union all 
        select 9 id, 7 num, trunc(sysdate, 'mm') + 3 dt from dual union all 
        select 10 id, 6 num, trunc(sysdate, 'mm') + 4 dt from dual union all 
        select 11 id, 6 num, trunc(sysdate, 'mm') + 4 dt from dual union all 
        select 12 id, 5 num, trunc(sysdate, 'mm') + 4 dt from dual union all 
        select 13 id, 6 num, trunc(sysdate, 'mm') + 5 dt from dual union all 
        select 14 id, 9 num, trunc(sysdate, 'mm') + 5 dt from dual union all 
        select 15 id, 3 num, trunc(sysdate, 'mm') + 5 dt from dual union all 
        select 16 id, 2 num, trunc(sysdate, 'mm') + 6 dt from dual), 
      res as (select id, 
          num, 
          dt st_dt, 
          dt + 3 end_dt, 
          count(*) over (partition by num order by dt 
              range between current row and 3 following) cnt_num_curr_and_next_3_days 
        from sample_data) 
select st_dt, 
     end_dt, 
     count(case when cnt_num_curr_and_next_3_days > 1 then 1 end) count_multiple, 
     count(case when cnt_num_curr_and_next_3_days = 1 then 1 end) count_single 
from res 
group by st_dt, 
     end_dt 
order by st_dt; 

ST_DT  END_DT  COUNT_MULTIPLE COUNT_SINGLE 
---------- ---------- -------------- ------------ 
02/07/2015 05/07/2015    2   1 
03/07/2015 06/07/2015    2   1 
04/07/2015 07/07/2015    0   3 
05/07/2015 08/07/2015    2   1 
06/07/2015 09/07/2015    0   3 
07/07/2015 10/07/2015    0   1 

我越是看这个,我越觉得也许这解析函数不能做的工作,至少不是他们自己的。

模型子句可能是最好的解决方案,但不幸的是,我不是模型专家!