[英]MySQL query with LEFT JOIN, GROUP BY and ORDER BY
我有兩個表, Users
和Visitors
。 在“ Users
,我具有所有用戶信息,在“ Visitors
我輸入了登錄結果。 每次用戶登錄時,新記錄都會使用user_id
和datetime
進入Visitors
。
我想選擇所有具有上次登錄日期的用戶 。 我怎樣才能做到這一點?
為了避免使用子查詢來計算每個用戶的最新時間(這實際上意味着對n
用戶運行n
查詢),請使用組的mysql“技巧” group by
無聚合),它返回每個組的第一行:
select u.*, last_login
from users u
left join (select id, last_login
from (select u.id, v.last_login
from users u
join visits v on v.user_id = u.id
order by 1, 2 desc
) x
group by 1) y on y.id = u.id;
該查詢的效果非常好,只需對訪問量表進行一次遍歷(9)(每個用戶都沒有子查詢)。
這是正在發生的事情的分解:
x
)按順序獲取用戶ID和last_visit,並在每個用戶ID中首先獲取我們想要的last_visit值 y
)使用基於用戶ID的group by
, 而不使用任何聚合函數。 在其他數據庫中,這將是一個錯誤,但是在mysql中,它返回每個組的第一行-即我們想要的last_visit值(因此對行進行了排序) left join
,為從未訪問過的用戶提供null
值,否則將我們要加入的last_visit加入用戶行 嘗試在選擇中使用子查詢
例如: select u.name,(select datetime from visitors v where u.id_user = v.id_user order by datetime desc limit 1) as lastlogin_datetme from users u;
SELECT cur.textID, cur.fromEmail, cur.subject,
cur.timestamp, cur.read
FROM incomingEmails cur
LEFT JOIN incomingEmails next
on cur.fromEmail = next.fromEmail
and cur.timestamp < next.timestamp
WHERE next.timestamp is null
and cur.toUserID = '$userID'
ORDER BY LOWER(cur.fromEmail)
Basically, you join the table on itself, searching for later rows.
在where子句中,您聲明以后不能再有行。 這僅給您最新行。
如果可以有多個具有相同時間戳的電子郵件,則此查詢將需要優化。 如果電子郵件表中有一個增量ID列,請按以下方式更改JOIN:
LEFT JOIN incomingEmails next
on cur.fromEmail = next.fromEmail
and cur.id < next.id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.