簡體   English   中英

如何在同一個表上多次加入每行的最大值

[英]How to join multiple times on the same table with the max value for each row

我有一個包含 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;

但這根本不能很好地擴展。

在我大部分為空的活動表上,如果我只執行第一個查詢,它將花費 4ms,但是一旦我添加第一個“MostRecentType2”加入它就會跳轉到 40ms,然后 MostRecentType3 go 到 80ms 並繼續以這種方式增加,在某些情況下我需要很多連接。

關於如何(更好地)進行查詢的任何想法?

嗯。 . . 您可以使用DISTINCT ON為每個用戶獲取每種類型的最新行。 然后只需使用條件聚合:

SELECT user_id,
       MAX(date_of_activity) FILTER (WHERE type_id = 1) as date_1,
       MAX(content_id) FILTER (WHERE type_id = 1) as content_1,
       MAX(date_of_activity) FILTER (WHERE type_id = 2) as date_2,
       MAX(content_id) FILTER (WHERE type_id = 2) as content_2,
       MAX(date_of_activity) FILTER (WHERE type_id = 3) as date_3,
       MAX(content_id) FILTER (WHERE type_id = 3) as content_3
FROM (SELECT DISTINCT ON (user_id, type_id) a.*
      FROM activities a
      WHERE a.deleted_at IS NULL
      ORDER BY user_id, type_id, date_of_activity DESC
     ) a
GROUP BY user_id

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM