我有 2 張桌子(人 活動)
人
| ID | 姓名 |
|---|---|
| 1 | 約翰 |
| 2 | 阿克塞爾 |
| 3 | 威廉 |
活動
| 活動編號 | person_id | 活動型別 |
|---|---|---|
| 1 | 1 | 登錄 |
| 2 | 1 | 訪問過的網站 |
| 3 | 1 | 登出 |
| 4 | 3 | 登錄 |
| 5 | 3 | 登出 |
如您所見,約翰和威廉都有多項活動。但阿克塞爾根本沒有任何活動。
我嘗試實作的結果如下。我想從person表的每個條目中選擇id和name,從activity表中選擇activity_id和activity_type。
如果此人還沒有活動,則仍應顯示此人的 ID 和姓名。如果此人有多個活動,則只應顯示 id 最高的活動。
我的目標是:
| ID | 姓名 | 活動編號 | 活動型別 |
|---|---|---|---|
| 1 | 約翰 | 3 | 登出 |
| 2 | 阿克塞爾 | 空值 | 空值 |
| 3 | 威廉 | 5 | 登出 |
當我嘗試左連接時:
select p.id, p.name, a.activity_id, a.activity_type
from person p left join activity a on p.id = a.person_id
order by p.id
我得到這個結果:
| ID | 姓名 | 活動編號 | 活動型別 |
|---|---|---|---|
| 1 | 約翰 | 1 | 登錄 |
| 1 | 約翰 | 2 | 訪問過的網站 |
| 1 | 約翰 | 3 | 登出 |
| 2 | 阿克塞爾 | 空值 | 空值 |
| 3 | 威廉 | 4 | 登錄 |
| 3 | 威廉 | 5 | 登出 |
但是因為我只想要一個人一個條目,所以我添加了以下 where 子句:
select p.id, p.name, a.activity_id, a.activity_type
from person p left join activity a on p.id = a.person_id
where a.id = (select max(id) from activity a2 where a2.person_id = p.id)
order by p.id
這是結果:
| ID | 姓名 | 活動編號 | 活動型別 |
|---|---|---|---|
| 1 | 約翰 | 3 | 登出 |
| 3 | 威廉 | 5 | 登出 |
約翰和威廉的條目是我想要的。僅顯示“最后”活動。問題是不再顯示 Axel。
任何幫助appriciated。提前謝謝了!
uj5u.com熱心網友回復:
在 Postgres 中,最簡單和最快的方法通常是使用 SQL 的 Postgres 擴展distinct on:
select distinct on (p.id) p.id, p.name, a.activity_id, a.activity_type
from person p left join
activity a
on p.id = a.person_id
order by p.id, a.activity_id desc;
distinct on為括號中指定的鍵回傳一行。具體行由order by.
為了性能,我建議像這樣撰寫查詢:
select p.id, p.name, a.activity_id, a.activity_type
from person p left join
(select distinct on (a.person_id) a.*
from activity a
order by a.person_id, a.activity_id desc
) a
on p.id = a.person_id;
然后在 上創建索引activity(person_id, activity_id desc)。
uj5u.com熱心網友回復:
您可以使用的另一種選擇,使用正確的索引可能會更高效,使用視窗函式來識別每個人的活動
select p.id, p.name, a.activity_id, a.activity_type
from person p
left join (
select *, Row_Number() over(partition by person_id order by activity_id desc) rn
from activities
)a on a.person_id=p.id and a.rn=1
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/315259.html
標籤:sql 加入 postgresql-9.4
