sql - SQL查询:一个表/时间序列对另一个表的反应,对于每个用户
问题描述
假设我有表A
和B
,它们都有超过 1 亿行包含 8 年的数据。它们都有列row_id
(=唯一的行标识符,例如行号)person_id
,,dt
(=日期时间)。中的一行A
表示用户打开电子邮件的时间。中的一行B
代表用户访问特定网站的时间。
我希望创建一个 table C
,它恰好附加A
了几个(比如说 10 个)列。C_i
这些列C_i
必须衡量,在用户打开一封电子邮件后(即在 A 中的一行中),i
他访问了该网站的次数(即在打开电子邮件后的几个小时内)(即在 A 中的几行计数B
) . 我怎样才能有效地构建C
?
我在 Oracle PL/SQL 中尝试仅添加一列C_1
:
SELECT
any_value(A.id),
any_value(A.person_id),
any_value(A.dt),
count(1) response_1h
FROM A, B
WHERE
A.person_id = B.person_id AND
0 <= B.dt - A.dt AND B.dt-A.dt<=1/24
GROUP BY A.row_id;
我收到一个错误(不是因为这个,而是因为类似的查询),我怀疑是因为加入的表太大:
ORA-01652:无法在表空间 TEMP_DEV 01652 中将临时段扩展 256。00000 -“无法在表空间 %s 中将临时段扩展 %s” *原因:无法为临时段分配所需块数的范围在指示的表空间中。*操作:使用 ALTER TABLESPACE ADD DATAFILE 语句将一个或多个文件添加到指定的表空间。
对 10 个新列执行此操作似乎远非最佳。有人愿意告诉我这是如何正确完成的吗?
解决方案
您可以使用条件聚合来计算网站访问量。下面的示例查看每条消息后的十小时并有条件地计数。
select
a.id, a.person_id, a.dt,
count(case when b.dt <= a.dt + interval '1' hour then 1 end) as response_1h,
count(case when b.dt <= a.dt + interval '2' hour then 1 end) as response_2h,
count(case when b.dt <= a.dt + interval '3' hour then 1 end) as response_3h,
count(case when b.dt <= a.dt + interval '4' hour then 1 end) as response_4h,
count(case when b.dt <= a.dt + interval '5' hour then 1 end) as response_5h,
count(case when b.dt <= a.dt + interval '6' hour then 1 end) as response_6h,
count(case when b.dt <= a.dt + interval '7' hour then 1 end) as response_7h,
count(case when b.dt <= a.dt + interval '8' hour then 1 end) as response_8h,
count(case when b.dt <= a.dt + interval '9' hour then 1 end) as response_9h,
count(b.dt) as response_10h
from a
left join b on b.person_id = a.person_id
and b.dt > a.dt
and b.dt <= a.dt + interval '10' hour
group by a.id, a.person_id, a.dt
order by a.id;
与横向连接相同:
select *
from a
outer apply
(
select
count(case when b.dt <= a.dt + interval '1' hour then 1 end) as response_1h,
count(case when b.dt <= a.dt + interval '2' hour then 1 end) as response_2h,
count(case when b.dt <= a.dt + interval '3' hour then 1 end) as response_3h,
count(case when b.dt <= a.dt + interval '4' hour then 1 end) as response_4h,
count(case when b.dt <= a.dt + interval '5' hour then 1 end) as response_5h,
count(case when b.dt <= a.dt + interval '6' hour then 1 end) as response_6h,
count(case when b.dt <= a.dt + interval '7' hour then 1 end) as response_7h,
count(case when b.dt <= a.dt + interval '8' hour then 1 end) as response_8h,
count(case when b.dt <= a.dt + interval '9' hour then 1 end) as response_9h,
count(b.dt) as response_10h
from b
where b.person_id = a.person_id
and b.dt > a.dt
and b.dt <= a.dt + interval '10' hour
)
order by a.id;
查看解释计划,看看一个是否应该比另一个运行得更快。
对于任一查询,您都需要表 b 上的复合索引,以便快速找到其匹配的行。由于索引中列的顺序很重要,我将添加两个可能的索引:
create index idx1 on b (person_id, dt);
create index idx2 on b (dt, person_id);
您始终可以删除未使用的索引。
至于 ORA-01652:我无法回答这个问题。也许您可以增加临时表空间的大小并解决问题。我不知道。
推荐阅读
- react-native - 如何在本机反应中显示获取的数据
- laravel - 如何通过输入序列号从某个产品的数据库中获取成本?
- tensorflow - 良好的训练准确性,但糟糕的评估
- java - Gradle 6.0 和 PMD 6.15 集成,当允许违反限制时如何使构建失败
- c# - 如何知道我是在 .NET Framework 还是 .NET Core 下运行
- scala - scala中的Spark SQL执行
- java - Spring RestTemplate 拦截器不执行请求
- mysql - sql查询显示正确的值但错误的'id'
- kubernetes - Kubernetes - HPA 指标 - 内存和 cpu 一起
- javascript - 提交后如何清除表格