连接具有不同数据维度的表(每周和每天)
Join Tables with different data dimensions (weekly and daily)
我有一个 table 每周采集数据,第二个 table 每天采集数据。我需要通过 id 键在 tables (INNER JOIN) 和每日 table 值之间建立联合,将它们平均每周汇总。
因此,我的结果 table 也将包含每周日期,并且对于每个星期,它应该显示前 7 天(包括获取当天)的 id 的平均值。
数据样本:DBfiddle
在提供的这个示例中,加入和分组操作返回了正确的结果。但是他取的是全局平均值,不是每个周采集日期对应的前7天的平均值。
有人知道解决这个问题的最佳方法吗?
子查询就足够了,但前提是您对每一行的最后 7 天都感兴趣
select id, rating, aquisition_date ,
(select avg(value) from table2 a2 where a2.id = a1.id and
a2.aquisition_date between a1.aquisition_date - 6 and a1.aquisition_date) avg
from table1 a1
结果
id
rating
aquisition_date
avg
1
10
2022-04-18
5
1
8.2
2022-04-25
14.57142
在附加示例中,您还提供了时间值(但由于 table 定义,它们在插入期间被切断)
简答:
您必须将周包括在 JOIN
:
SELECT
table1.id
,EXTRACT(WEEK FROM table1.aquisition_date) AS week
,table1.rating AS table1_rating
,AVG(table2.value) as table2_value_avg
FROM
table1 table1
INNER JOIN
table2 table2
ON
table2.id = table1.id AND
EXTRACT(WEEK FROM table1.aquisition_date) = EXTRACT(WEEK FROM table2.aquisition_date)
GROUP BY
table1.id
,table1.rating
,table1.aquisition_date
;
这给了我们
id week table1_rating table2_value_avg
1 17 8.2 20.0000000000000000
1 16 10 13.1428571428571429
长答案:
我们怎么去那里?考虑内部联接 没有 聚合:
您的第一次尝试是
SELECT
table1.id
,EXTRACT(WEEK FROM table1.aquisition_date) AS week1
,EXTRACT(WEEK FROM table2.aquisition_date) AS week2
-- ,AVG(EXTRACT(WEEK FROM table2.aquisition_date)) AS week2
,table1.rating AS table1_rating
,table2.value AS table2_value
-- ,AVG(table2.value) as table2_value_avg
FROM
table1 table1
INNER JOIN
table2 table2
ON
table2.id = table1.id
这将匹配两个表中不属于一起的行,例如第 15 周的值和第 16 周的评分。
id week1 week2 table1_rating table2_value
1 16 15 10 2
1 16 15 10 4
[... 40 more rows]
实际上它匹配表 1 和表 2 的每一行。这就是为什么平均值是全球平均值,即使 GROUP BY
有效。
所以上面的解决方案是从内部连接中删除那些星期不匹配的行。
N.B.: 如果你想在只有一个表有数据的结果中包含数据,你需要 FULL OUTER JOIN
但想法是一样的。
N.B.:(感谢@shawnt00)(从...中提取周)表示ISO 8601 week。它从星期一开始,一周可能还有其他定义。
N.B.:(感谢@shawnt00)该解决方案忽略了年份。如果存在超过一年的数据,您需要匹配 JOIN 中的年份和星期。
我有一个 table 每周采集数据,第二个 table 每天采集数据。我需要通过 id 键在 tables (INNER JOIN) 和每日 table 值之间建立联合,将它们平均每周汇总。
因此,我的结果 table 也将包含每周日期,并且对于每个星期,它应该显示前 7 天(包括获取当天)的 id 的平均值。
数据样本:DBfiddle
在提供的这个示例中,加入和分组操作返回了正确的结果。但是他取的是全局平均值,不是每个周采集日期对应的前7天的平均值。
有人知道解决这个问题的最佳方法吗?
子查询就足够了,但前提是您对每一行的最后 7 天都感兴趣
select id, rating, aquisition_date ,
(select avg(value) from table2 a2 where a2.id = a1.id and
a2.aquisition_date between a1.aquisition_date - 6 and a1.aquisition_date) avg
from table1 a1
结果
id | rating | aquisition_date | avg |
---|---|---|---|
1 | 10 | 2022-04-18 | 5 |
1 | 8.2 | 2022-04-25 | 14.57142 |
在附加示例中,您还提供了时间值(但由于 table 定义,它们在插入期间被切断)
简答:
您必须将周包括在 JOIN
:
SELECT
table1.id
,EXTRACT(WEEK FROM table1.aquisition_date) AS week
,table1.rating AS table1_rating
,AVG(table2.value) as table2_value_avg
FROM
table1 table1
INNER JOIN
table2 table2
ON
table2.id = table1.id AND
EXTRACT(WEEK FROM table1.aquisition_date) = EXTRACT(WEEK FROM table2.aquisition_date)
GROUP BY
table1.id
,table1.rating
,table1.aquisition_date
;
这给了我们
id week table1_rating table2_value_avg
1 17 8.2 20.0000000000000000
1 16 10 13.1428571428571429
长答案: 我们怎么去那里?考虑内部联接 没有 聚合:
您的第一次尝试是
SELECT
table1.id
,EXTRACT(WEEK FROM table1.aquisition_date) AS week1
,EXTRACT(WEEK FROM table2.aquisition_date) AS week2
-- ,AVG(EXTRACT(WEEK FROM table2.aquisition_date)) AS week2
,table1.rating AS table1_rating
,table2.value AS table2_value
-- ,AVG(table2.value) as table2_value_avg
FROM
table1 table1
INNER JOIN
table2 table2
ON
table2.id = table1.id
这将匹配两个表中不属于一起的行,例如第 15 周的值和第 16 周的评分。
id week1 week2 table1_rating table2_value
1 16 15 10 2
1 16 15 10 4
[... 40 more rows]
实际上它匹配表 1 和表 2 的每一行。这就是为什么平均值是全球平均值,即使 GROUP BY
有效。
所以上面的解决方案是从内部连接中删除那些星期不匹配的行。
N.B.: 如果你想在只有一个表有数据的结果中包含数据,你需要 FULL OUTER JOIN
但想法是一样的。
N.B.:(感谢@shawnt00)(从...中提取周)表示ISO 8601 week。它从星期一开始,一周可能还有其他定义。
N.B.:(感谢@shawnt00)该解决方案忽略了年份。如果存在超过一年的数据,您需要匹配 JOIN 中的年份和星期。