我有两个表,一个存储用户,另一个存储用户的电子邮件地址。
userId
,username
,etc
)emailId
,userId
,email
)我想做一个查询,允许我获取最新的电子邮件地址和用户记录 我基本上在寻找一个说
的查询FIRST ORDER BY userEmail.emailId DESC
THEN GROUP BY userEmail.userId
这可以通过以下方式完成:
SELECT
users.userId
, users.username
, (
SELECT
userEmail.email
FROM userEmail
WHERE userEmail.userId = users.userId
ORDER BY userEmail.emailId DESC
LIMIT 1
) AS email
FROM users
ORDER BY users.username;
但是这会为每一行做一个子查询,效率非常低。 (在我的程序逻辑中执行2个单独的查询并将它们“连接”在一起会更快。)
为我想要的东西写的直观查询将是:
SELECT
users.userId
, users.username
, userEmail.email
FROM users
LEFT JOIN userEmail USING(userId)
GROUP BY users.userId
ORDER BY
userEmail.emailId
, users.username;
但是,这并不像我想的那样起作用。 (GROUP BY
在排序之前执行,因此ORDER BY userEmail.emailId
无关。)
所以我的问题是:
是否可以在不使用子查询的情况下编写第一个查询?
我已经搜索并阅读了有关stackoverflow的其他问题,但似乎没有人回答有关此查询模式的问题。
答案 0 :(得分:5)
但是这会为每一行做一个子查询并且效率非常低
首先,你有一个证明这个的查询计划/时间表吗?你完成它的方式(使用subselect)几乎是“直观”的方式。许多DBMS(虽然我不确定MySQL)对这种情况有优化,并且只能执行一次查询。
或者,您应该能够在其上创建仅包含(user id, latest email id)
元组和JOIN
的子表:
SELECT
users.userId
, users.username
, userEmail.email
FROM users
INNER JOIN
(SELECT userId, MAX(emailId) AS latestEmailId
FROM userEmail GROUP BY userId)
AS latestEmails
ON (users.userId = latestEmails.userId)
INNER JOIN userEmail ON
(latestEmails.latestEmailId = userEmail.emailId)
ORDER BY users.username;
答案 1 :(得分:1)
如果这是您经常进行的查询,我建议您优化表格来处理此问题。
我建议在emailId
表格中添加users
列。当用户更改其电子邮件地址或将旧电子邮件地址设置为主电子邮件地址时,请更新users
表中的用户行以指示当前的emailId
修改代码以执行此更新后,您可以返回并更新旧数据,为所有用户设置emailId
。
或者,您可以在email
表格中添加users
列,这样您就不必进行联接即可获取用户当前的电子邮件地址。