oracle SQL选择过去x天滚动期内的不同客户

oracle SQL选择过去x天滚动期内的不同客户,sql,oracle,oracle11g,window-functions,analytic-functions,Sql,Oracle,Oracle11g,Window Functions,Analytic Functions,假设您有一个日期如下的客户表: [客户表格] +----------+-----------+----------+ | customer | date | purchase | +----------+-----------+----------+ | 1 | 1/01/2016 | 12 | +----------+-----------+----------+ | 1 | 1/12/2016 | 3 | +----------

假设您有一个日期如下的客户表:
[客户表格]

+----------+-----------+----------+
| customer | date      | purchase |
+----------+-----------+----------+
| 1        | 1/01/2016 | 12       |
+----------+-----------+----------+
| 1        | 1/12/2016 | 3        |
+----------+-----------+----------+
| 2        | 5/03/2016 | 5        |
+----------+-----------+----------+
| 3        | 1/16/2016 | 6        |
+----------+-----------+----------+
| 3        | 3/22/2016 | 1        |
+----------+-----------+----------+  
我想写一个查询,从每个日历日算起,向后算10天,计算过去10天内有多少不同的客户进行了购买。因此,对于2016年的每一个独特的日子,最终输出将是一个日历,其中每一天都有一个在该日历的前10天存在的不同客户计数,如下所示:
[结果表]

+-----------+------------------+
| date      | unique customers |
+-----------+------------------+
| 1/01/2016 | 112              |
+-----------+------------------+
| 1/02/2016 | 104              |
+-----------+------------------+
| 1/03/2016 | 140              |
+-----------+------------------+
| 1/04/2016 | 133              |
+-----------+------------------+
| ....      | 121              |
+-----------+------------------+  
我提出的一个解决方案是创建一个只有一列的日历表,然后使用不平等连接将日历表连接到客户表。我认为这是非常低效的,我正在寻求更快的解决方案。因此,我的第一步是创建一个日历,如下所示:
[日历]

+-----------+
| date      |
+-----------+
| 1/01/2016 |
+-----------+
| 1/02/2016 |
+-----------+
| 1/03/2016 |
+-----------+
| 1/04/2016 |
+-----------+
| 1/05/2016 |
+-----------+  
然后,对于日历中的每一天,为了在每一天之前统计不同的客户群,我加入一个不等式,如下所示:

select
count(distinct customer) as unique customers
from calendar c
left join mytable m
on c.date>=m.date and m.date>=c.date-10  
虽然我相信这是正确的,但它运行速度非常慢(比如说有几百万客户的日历的2年)。有没有oracle的分析功能可以帮助我

有没有oracle的分析功能可以帮助我

不是真的-从:

如果指定
DISTINCT
,则只能指定分析子句的
query\u partition\u子句
。不允许使用
order\u by\u子句
windowing\u子句

您可能需要
不同的
和不允许的
窗口化子句

更新

CREATE TABLE table_name ( customer, dt ) AS
  SELECT 1, DATE '2017-01-10' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-11' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-15' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-20' FROM DUAL UNION ALL
  SELECT 2, DATE '2017-01-12' FROM DUAL UNION ALL
  SELECT 2, DATE '2017-01-19' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-10' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-13' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-15' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-20' FROM DUAL;
DAY                 UNIQUE_CUSTOMERS
------------------- ----------------
2017-01-01 00:00:00                0
2017-01-02 00:00:00                0
2017-01-03 00:00:00                0
2017-01-04 00:00:00                0
2017-01-05 00:00:00                0
2017-01-06 00:00:00                0
2017-01-07 00:00:00                0
2017-01-08 00:00:00                0
2017-01-09 00:00:00                0
2017-01-10 00:00:00                2
2017-01-11 00:00:00                2
2017-01-12 00:00:00                3
2017-01-13 00:00:00                3
2017-01-14 00:00:00                2
2017-01-15 00:00:00                2
2017-01-16 00:00:00                2
2017-01-17 00:00:00                2
2017-01-18 00:00:00                0
2017-01-19 00:00:00                1
2017-01-20 00:00:00                3
2017-01-21 00:00:00                3
2017-01-22 00:00:00                2
2017-01-23 00:00:00                0
2017-01-24 00:00:00                0
2017-01-25 00:00:00                0
2017-01-26 00:00:00                0
2017-01-27 00:00:00                0
2017-01-28 00:00:00                0
2017-01-29 00:00:00                0
2017-01-30 00:00:00                0
2017-01-31 00:00:00                0
使用按客户划分的非不同的分析查询组合,然后按天聚合,可以获得与无效语法相同的效果:

Oracle安装程序

CREATE TABLE table_name ( customer, dt ) AS
  SELECT 1, DATE '2017-01-10' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-11' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-15' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-20' FROM DUAL UNION ALL
  SELECT 2, DATE '2017-01-12' FROM DUAL UNION ALL
  SELECT 2, DATE '2017-01-19' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-10' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-13' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-15' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-20' FROM DUAL;
DAY                 UNIQUE_CUSTOMERS
------------------- ----------------
2017-01-01 00:00:00                0
2017-01-02 00:00:00                0
2017-01-03 00:00:00                0
2017-01-04 00:00:00                0
2017-01-05 00:00:00                0
2017-01-06 00:00:00                0
2017-01-07 00:00:00                0
2017-01-08 00:00:00                0
2017-01-09 00:00:00                0
2017-01-10 00:00:00                2
2017-01-11 00:00:00                2
2017-01-12 00:00:00                3
2017-01-13 00:00:00                3
2017-01-14 00:00:00                2
2017-01-15 00:00:00                2
2017-01-16 00:00:00                2
2017-01-17 00:00:00                2
2017-01-18 00:00:00                0
2017-01-19 00:00:00                1
2017-01-20 00:00:00                3
2017-01-21 00:00:00                3
2017-01-22 00:00:00                2
2017-01-23 00:00:00                0
2017-01-24 00:00:00                0
2017-01-25 00:00:00                0
2017-01-26 00:00:00                0
2017-01-27 00:00:00                0
2017-01-28 00:00:00                0
2017-01-29 00:00:00                0
2017-01-30 00:00:00                0
2017-01-31 00:00:00                0
查询

CREATE TABLE table_name ( customer, dt ) AS
  SELECT 1, DATE '2017-01-10' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-11' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-15' FROM DUAL UNION ALL
  SELECT 1, DATE '2017-01-20' FROM DUAL UNION ALL
  SELECT 2, DATE '2017-01-12' FROM DUAL UNION ALL
  SELECT 2, DATE '2017-01-19' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-10' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-13' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-15' FROM DUAL UNION ALL
  SELECT 3, DATE '2017-01-20' FROM DUAL;
DAY                 UNIQUE_CUSTOMERS
------------------- ----------------
2017-01-01 00:00:00                0
2017-01-02 00:00:00                0
2017-01-03 00:00:00                0
2017-01-04 00:00:00                0
2017-01-05 00:00:00                0
2017-01-06 00:00:00                0
2017-01-07 00:00:00                0
2017-01-08 00:00:00                0
2017-01-09 00:00:00                0
2017-01-10 00:00:00                2
2017-01-11 00:00:00                2
2017-01-12 00:00:00                3
2017-01-13 00:00:00                3
2017-01-14 00:00:00                2
2017-01-15 00:00:00                2
2017-01-16 00:00:00                2
2017-01-17 00:00:00                2
2017-01-18 00:00:00                0
2017-01-19 00:00:00                1
2017-01-20 00:00:00                3
2017-01-21 00:00:00                3
2017-01-22 00:00:00                2
2017-01-23 00:00:00                0
2017-01-24 00:00:00                0
2017-01-25 00:00:00                0
2017-01-26 00:00:00                0
2017-01-27 00:00:00                0
2017-01-28 00:00:00                0
2017-01-29 00:00:00                0
2017-01-30 00:00:00                0
2017-01-31 00:00:00                0
注意:下面的查询仅针对一个月的数据以及之前两天的范围来说明原理,但将参数更改为12个月10天是很容易的


你能提供一些样本数据和输出吗?我有一些想法想测试一下……mytable中总共有多少条记录?表中有多少不同的客户?数据是敏感的抱歉,我在一个2年的日历上运行此功能,有不到1000万但超过500000个不同的客户。所以你认为唯一的方法是三角形联接/交叉联接吗?@barker找到了一种结合分析和聚合函数以及分区联接的方法。。。不知道与范围条件下的外部联接相比,它将如何执行,因此您需要分析两个查询并进行比较。尝试此查询时,我用完了临时数据。但是它很聪明,也很好。啊,这可能是答案,我得测试一下,看看哪个生产速度更快。所以我相信“最小”函数是正确的,因为前面的函数会对同一个客户进行多次计数,最小值会强制值为1或0正确吗?因此,总和是不同的。@巴克这是正确的,使用(…)上的
COUNT()和
最小值的组合来确定该范围内是否有客户购买,然后这些值上的
sum
使其类似于
COUNT(distinct…)OVER(window)