计算每次购买前 30 天按来源的访问次数
Count Visits by Source for 30 Day Prior Period for each Purchase
我有一个 table 记录网站 activity,其中包含以下列和数据
ID Date Source Revenue
1 2013-10-01 A 0
2 2013-10-01 A 0
3 2013-10-01 B 10
1 2013-10-02 A 40
4 2013-10-03 B 0
3 2013-10-03 B 0
4 2013-10-04 A 10
我正在尝试创建一个 table 来获取每笔交易(收入 > 0),并在过去 30 天的各个列中按来源统计所有访问。它应该看起来像这样。
ID Date Source Revenue Count_A Count_B
3 2013-10-01 B 10 0 1
1 2013-10-02 A 40 2 0
4 2013-10-04 A 10 1 1
我已尝试对这些列中的每一列使用子查询,但计数偏差很大,我不确定为什么。
Select ID,
Date,
Source,
Revenue,
(SELECT Count(*)
FROM table t2
WHERE t2.Date between t.Date-30 and t.Date and Source = 'A') AS Count_A
(SELECT Count(*)
FROM table t3
WHERE t3.Date between t.Date-30 and t.Date and Source = 'B') AS Count_B
FROM table t
Where Revenue > 0
Order By WMEID
我正在使用 Microsoft SQL 服务器。
您的计数不对,因为您的子 select 与外部查询不相关,因此总计独立于行中的其他数据。此外,子 select 中没有 GROUP BY
,因此您得到的总数是 table。我不太确定那个日期逻辑。
您可以通过将相关性添加到每个子select(WHERE...t2.ID = t.ID AND t2.Date = t.Date, etc
)并包含适当的GROUP BY
子句来纠正所有这些对于每个查询。但这是相当多的输入,难以维护,也难以阅读。它还可能会生成多个 table 扫描,因此可能会成为性能问题。
相反,我会选择条件聚合:
Select t.ID,
t.Date,
t.Source,
SUM(t.Revenue) AS Revenue,
SUM(CASE WHEN t.Source = 'A' THEN 1 ELSE 0 END) AS Count_A,
SUM(CASE WHEN t.Source = 'B' THEN 1 ELSE 0 END) AS Count_B
FROM mytable t
Where Revenue > 0
AND t.Date >= DATEADD(DAY, -30, CAST(GETDATE() AS date))
AND t.Date < CAST(GETDATE() AS date)
GROUP BY
t.ID,
t.Date,
t.Source
Order By t.Date
结果(基于问题中的结构,而非数据):
+----+------------+--------+---------+---------+---------+
| ID | Date | Source | Revenue | Count_A | Count_B |
+----+------------+--------+---------+---------+---------+
| 3 | 2020-05-01 | B | 60 | 0 | 2 |
| 1 | 2020-05-02 | A | 40 | 1 | 0 |
| 4 | 2020-05-04 | A | 10 | 1 | 0 |
+----+------------+--------+---------+---------+---------+
这里是 SQL Fiddle。
使用横向连接:
Select l.*, l2.*
from logs l outer apply
(select sum(case when l2.source = 'A' then 1 else 0 end) as count_a,
sum(case when l2.source = 'B' then 1 else 0 end) as count_b
from logs l2
where l2.id = l.id and
l2.date >= dateadd(day, -30, l.date) and
l2.date <= l.date
) l2
where l.Revenue > 0
order By l.WMEID;
我认为您的方法存在问题,因为您没有匹配 ID。
我有一个 table 记录网站 activity,其中包含以下列和数据
ID Date Source Revenue
1 2013-10-01 A 0
2 2013-10-01 A 0
3 2013-10-01 B 10
1 2013-10-02 A 40
4 2013-10-03 B 0
3 2013-10-03 B 0
4 2013-10-04 A 10
我正在尝试创建一个 table 来获取每笔交易(收入 > 0),并在过去 30 天的各个列中按来源统计所有访问。它应该看起来像这样。
ID Date Source Revenue Count_A Count_B
3 2013-10-01 B 10 0 1
1 2013-10-02 A 40 2 0
4 2013-10-04 A 10 1 1
我已尝试对这些列中的每一列使用子查询,但计数偏差很大,我不确定为什么。
Select ID,
Date,
Source,
Revenue,
(SELECT Count(*)
FROM table t2
WHERE t2.Date between t.Date-30 and t.Date and Source = 'A') AS Count_A
(SELECT Count(*)
FROM table t3
WHERE t3.Date between t.Date-30 and t.Date and Source = 'B') AS Count_B
FROM table t
Where Revenue > 0
Order By WMEID
我正在使用 Microsoft SQL 服务器。
您的计数不对,因为您的子 select 与外部查询不相关,因此总计独立于行中的其他数据。此外,子 select 中没有 GROUP BY
,因此您得到的总数是 table。我不太确定那个日期逻辑。
您可以通过将相关性添加到每个子select(WHERE...t2.ID = t.ID AND t2.Date = t.Date, etc
)并包含适当的GROUP BY
子句来纠正所有这些对于每个查询。但这是相当多的输入,难以维护,也难以阅读。它还可能会生成多个 table 扫描,因此可能会成为性能问题。
相反,我会选择条件聚合:
Select t.ID,
t.Date,
t.Source,
SUM(t.Revenue) AS Revenue,
SUM(CASE WHEN t.Source = 'A' THEN 1 ELSE 0 END) AS Count_A,
SUM(CASE WHEN t.Source = 'B' THEN 1 ELSE 0 END) AS Count_B
FROM mytable t
Where Revenue > 0
AND t.Date >= DATEADD(DAY, -30, CAST(GETDATE() AS date))
AND t.Date < CAST(GETDATE() AS date)
GROUP BY
t.ID,
t.Date,
t.Source
Order By t.Date
结果(基于问题中的结构,而非数据):
+----+------------+--------+---------+---------+---------+
| ID | Date | Source | Revenue | Count_A | Count_B |
+----+------------+--------+---------+---------+---------+
| 3 | 2020-05-01 | B | 60 | 0 | 2 |
| 1 | 2020-05-02 | A | 40 | 1 | 0 |
| 4 | 2020-05-04 | A | 10 | 1 | 0 |
+----+------------+--------+---------+---------+---------+
这里是 SQL Fiddle。
使用横向连接:
Select l.*, l2.*
from logs l outer apply
(select sum(case when l2.source = 'A' then 1 else 0 end) as count_a,
sum(case when l2.source = 'B' then 1 else 0 end) as count_b
from logs l2
where l2.id = l.id and
l2.date >= dateadd(day, -30, l.date) and
l2.date <= l.date
) l2
where l.Revenue > 0
order By l.WMEID;
我认为您的方法存在问题,因为您没有匹配 ID。