【发布时间】:2021-07-28 16:50:57
【问题描述】:
我有一个包含 5 个字段的表格活动:
id - numeric
user_id - numeric
type_id - numeric
content_id - numeric
date_of_activity date
我需要做一个查询,其结果将是 7 列:
id(type1 activity),content_id(type 1) at max(date_of_activity for type 1),max(date_of_activity for type 1)content_id(type 2) at max(date_of_activity for type 2),max(date_of_activity for type 2)content_id(type 3) at max(date_of_activity for type 3),max(date_of_activity for type 3)
如果用户的 type_id 没有对应的值,则对应列中应显示 NULL 值。
例子:
users
user_id: 1
user_id: 2
user_id: 3
activities
id: 1
user_id: 1
type_id: 2
date_of_activity: 2021/05/01
content_id: 12
id: 2
user_id: 1
type_id: 3
date_of_activity: 2021/05/01
content_id: 102
id: 3
user_id: 2
type_id: 3
date_of_activity: 2021/05/01
content_id: 213
id: 4
user_id: 1
type_id: 2
date_of_activity: 2021/05/02
content_id: 13
id: 5
user_id: 1
type_id: 3
date_of_activity: 2021/05/02
content_id: 103
id: 6
user_id: 1
type_id: 1
date_of_activity: 2021/05/03
content_id: 1
id: 7
user_id: 2
type_id: 1
date_of_activity: 2021/05/03
content_id: 212
id: 8
user_id: 1
type_id: 3
date_of_activity: 2021/05/03
content_id: 104
id: 8
user_id: 1
type_id: 3
date_of_activity: 2021/05/04
content_id: 105
id: 10
user_id: 1
type_id: 1
date_of_activity: 2021/05/05
content_id: 2
id: 11
user_id: 1
type_id: 3
date_of_activity: 2021/05/05
content_id: 106
结果应该是:
id:10,
user_id:1,
type_id:1,
date_of_activity: 2021/05/05,
activity2.date_of_activity:2021/05/02,
activity2.content_id:13,
activity3.date_of_activity: 2021/05/05,
activity3.content_id:106
id:7,
user_id: 2,
type_id: 1,
date_of_activity: 2021/05/03,
content_id: 212,
activity2.date_of_activity: NULL,
activity2.content_id: NULL,
activity3.date_of_activity:2021/05/01
activity3.content_id:213
如您所见,我检索了一个活动,每个用户的每个活动类型,每个活动都是最新的,等等所有用户...
我有一个查询,可以检索每个用户的 ONE 活动类型的最新活动:
SELECT
activities.*,
dDates.max
FROM activities
JOIN users on users.id = activities.user_id
INNER JOIN (SELECT user_id,max(activities.date_of_activity) FROM activities WHERE activities.type_id = 6 AND activities.deleted_at IS NULL group by user_id) as dDates on activities.user_id = maxDates.user_id
WHERE activities.type_id = 6 AND activities.deleted_at IS NULL AND activities.date_of_activity = dDates.max;
但有时我需要将多个活动作为同一个查询的一部分加入,所以我试图一次获取所有内容,但我找不到一种不是很慢的方法。
我尝试为每种类型创建一个视图/使用“With”:
CREATE VIEW MostRecentType1 AS
SELECT
activities.*,
dDates.max
FROM activities
JOIN users on users.id = activities.user_id
INNER JOIN (SELECT user_id,max(activities.date_of_activity) FROM activities WHERE activities.type_id = 1 AND activities.deleted_at IS NULL group by user_id) as dDates on activities.user_id = maxDates.user_id
WHERE activities.type_id = 1 AND activities.deleted_at IS NULL AND activities.date_of_activity = dDates.max;
CREATE VIEW MostRecentType2 AS
SELECT
activities.*,
dDates.max
FROM activities
JOIN users on users.id = activities.user_id
INNER JOIN (SELECT user_id,max(activities.date_of_activity) FROM activities WHERE activities.type_id = 1 AND activities.deleted_at IS NULL group by user_id) as dDates on activities.user_id = maxDates.user_id
WHERE activities.type_id = 1 AND activities.deleted_at IS NULL AND activities.date_of_activity = dDates.max;
最后是视图的左连接
SELECT
activities.*,
dDates.max,
type2.date_of_activity as "type2.date_of_activity as",
type2.content_id as "type2.content_id",
type3.date_of_activity as "type3.date_of_activity" ,
type3.content_id as "type3.content_id" ,
FROM activities
JOIN users on users.id = activities.user_id
INNER JOIN (SELECT user_id,max(activities.date_of_activity) FROM activities WHERE activities.type_id = 1 AND activities.deleted_at IS NULL group by user_id) as dDates on activities.user_id = maxDates.user_id
LEFT JOIN MostRecentType2 as type2 on activities.user_id = type2.user_id
LEFT JOIN MostRecentType3 as type3 on activities.user_id = type3.user_id
WHERE activities.type_id = 1 AND activities.deleted_at IS NULL AND activities.date_of_activity = dDates.max;
但这根本不能很好地扩展。
在我大部分为空的活动表上,如果我只执行第一个查询,它将需要 4 毫秒,但是一旦我添加第一个“MostRecentType2”加入它就会跳转 到 40 毫秒,然后 MostRecentType3 到 80 毫秒并继续以这种方式递增,在某些情况下我需要大量的连接。
关于如何(更好地)进行查询的任何想法?
【问题讨论】:
标签: sql postgresql join query-optimization