select 如何从 user 和 usermeta 表中获取最后的用户信息?
How select last user information from user and usermeta tables?
我正在使用 mysql,我有两个表格如下:
User:
user_id - user_name - phone
UserMeta:
user_meta_id - user_id - meta_key - meta_value - meta_date
我有如下一些记录:
user_id: 23
meta_key: gender
meta_value: male
meta_date: 1534533650
user_id: 23
meta_key: city
meta_value: london
meta_date: 1534533650
user_id: 23
meta_key: name
meta_value: jack
meta_date: 1534533650
user_id: 25
meta_key: name
meta_value: Jamie
meta_date: 1534593881
user_id: 25
meta_key: gender
meta_value: male
meta_date: 1534593881
user_id: 23
meta_key: gender
meta_value: female
meta_date: 1534595971
user_id: 23
meta_key: city
meta_value: liverpool
meta_date: 1534595971
And ...
我需要获取所有用户信息 (user_id = 23),并注册了 最新 更改,例如:
user_id: 23
meta_key: name
meta_value: Jamie
meta_date: 1534533650
user_id: 23
meta_key: city
meta_value: liverpool
meta_date: 1534595971
user_id: 23
meta_key: gender
meta_value: female
meta_date: 1534595971
这个操作的查询很复杂,我很困惑,请帮助我,
我用了这个但没有得到正确的结果:
"SELECT kmu.*
FROM user_meta kmu
INNER JOIN
(SELECT `meta_key`, `meta_value`, MAX(`meta_date`) AS MaxDateTime
FROM user_meta
GROUP BY meta_key) groupedtt
ON user_id=:id
AND kmu.meta_key = groupedtt.meta_key
AND kmu.meta_date = groupedtt.MaxDateTime";
您可以使用以下内容:
SELECT `user`.*, user_meta.meta_key, user_meta.meta_value, user_meta.meta_date
FROM `user` INNER JOIN (
SELECT user_id, meta_key, MAX(meta_date) AS meta_date
FROM user_meta
GROUP BY user_id, meta_key
) meta_select ON `user`.user_id = meta_select.user_id
INNER JOIN user_meta ON meta_select.meta_key = user_meta.meta_key
AND meta_select.user_id = user_meta.user_id
AND meta_select.meta_date = user_meta.meta_date
WHERE `user`.user_id = 23
虽然我强烈反对这样的实施,但我不会试图改变您的想法。
虽然有很多方法可以实现这一点,但我相信下面的查询对性能的影响最小(不使用聚合)。
SELECT
user.*, meta.meta_key, meta.meta_value, meta.meta_date FROM user
LEFT JOIN
(
SELECT * FROM
(SELECT * FROM user_meta WHERE user_id = 23 ORDER BY meta_date DESC) sub
GROUP BY
sub.meta_key
) meta
ON
user.user_id = meta.user_id
ORDER BY
meta.meta_key;
为了便于阅读,我将查询格式化为这样。您可能会看到我使用了 2 个嵌套子查询。该要求来自这样一个事实,即当您使用 GROUP BY 子句时,ORDER BY 无效。因此,首先我们 select 行并按日期 desc 对它们进行排序,然后我们进行分组。这样它就保留了排序顺序。
请参阅工作解决方案 here,另请注意,我在左侧窗格中的示例数据库创建脚本中添加了 2 个 INDEX CREATE 语句。随着数据库的增长,这些都是最低限度的,以确保至少有足够的性能。
我想提出一个基于 ROW_NUMBER function. This solution has been broadly using in other databases. For example, look at here. But your version of MySQL doesn't support the ROW_NUMBER function and i used its emulation described here. To check my solution, click here 的解决方案。
SELECT
*
FROM `user` AS u
LEFT JOIN (
SELECT
t.*
FROM (
SELECT
@rn := IF(@uid = user_id AND @mk = meta_key, @rn + 1, 1) AS rn,
@uid := user_id AS uid,
@mk := meta_key AS mk,
um.*
FROM `user_meta` AS um
CROSS JOIN (SELECT @uid := 0, @mk := 0, @rn := 0) AS i
ORDER BY um.user_id, um.meta_key, um.meta_date DESC
) AS t
WHERE t.rn = 1
) AS r ON u.user_id = r.user_id
WHERE u.user_id = 23
我正在使用 mysql,我有两个表格如下:
User:
user_id - user_name - phoneUserMeta:
user_meta_id - user_id - meta_key - meta_value - meta_date
我有如下一些记录:
user_id: 23
meta_key: gender
meta_value: male
meta_date: 1534533650
user_id: 23
meta_key: city
meta_value: london
meta_date: 1534533650
user_id: 23
meta_key: name
meta_value: jack
meta_date: 1534533650
user_id: 25
meta_key: name
meta_value: Jamie
meta_date: 1534593881
user_id: 25
meta_key: gender
meta_value: male
meta_date: 1534593881
user_id: 23
meta_key: gender
meta_value: female
meta_date: 1534595971
user_id: 23
meta_key: city
meta_value: liverpool
meta_date: 1534595971
And ...
我需要获取所有用户信息 (user_id = 23),并注册了 最新 更改,例如:
user_id: 23
meta_key: name
meta_value: Jamie
meta_date: 1534533650
user_id: 23
meta_key: city
meta_value: liverpool
meta_date: 1534595971
user_id: 23
meta_key: gender
meta_value: female
meta_date: 1534595971
这个操作的查询很复杂,我很困惑,请帮助我,
我用了这个但没有得到正确的结果:
"SELECT kmu.*
FROM user_meta kmu
INNER JOIN
(SELECT `meta_key`, `meta_value`, MAX(`meta_date`) AS MaxDateTime
FROM user_meta
GROUP BY meta_key) groupedtt
ON user_id=:id
AND kmu.meta_key = groupedtt.meta_key
AND kmu.meta_date = groupedtt.MaxDateTime";
您可以使用以下内容:
SELECT `user`.*, user_meta.meta_key, user_meta.meta_value, user_meta.meta_date
FROM `user` INNER JOIN (
SELECT user_id, meta_key, MAX(meta_date) AS meta_date
FROM user_meta
GROUP BY user_id, meta_key
) meta_select ON `user`.user_id = meta_select.user_id
INNER JOIN user_meta ON meta_select.meta_key = user_meta.meta_key
AND meta_select.user_id = user_meta.user_id
AND meta_select.meta_date = user_meta.meta_date
WHERE `user`.user_id = 23
虽然我强烈反对这样的实施,但我不会试图改变您的想法。 虽然有很多方法可以实现这一点,但我相信下面的查询对性能的影响最小(不使用聚合)。
SELECT
user.*, meta.meta_key, meta.meta_value, meta.meta_date FROM user
LEFT JOIN
(
SELECT * FROM
(SELECT * FROM user_meta WHERE user_id = 23 ORDER BY meta_date DESC) sub
GROUP BY
sub.meta_key
) meta
ON
user.user_id = meta.user_id
ORDER BY
meta.meta_key;
为了便于阅读,我将查询格式化为这样。您可能会看到我使用了 2 个嵌套子查询。该要求来自这样一个事实,即当您使用 GROUP BY 子句时,ORDER BY 无效。因此,首先我们 select 行并按日期 desc 对它们进行排序,然后我们进行分组。这样它就保留了排序顺序。
请参阅工作解决方案 here,另请注意,我在左侧窗格中的示例数据库创建脚本中添加了 2 个 INDEX CREATE 语句。随着数据库的增长,这些都是最低限度的,以确保至少有足够的性能。
我想提出一个基于 ROW_NUMBER function. This solution has been broadly using in other databases. For example, look at here. But your version of MySQL doesn't support the ROW_NUMBER function and i used its emulation described here. To check my solution, click here 的解决方案。
SELECT
*
FROM `user` AS u
LEFT JOIN (
SELECT
t.*
FROM (
SELECT
@rn := IF(@uid = user_id AND @mk = meta_key, @rn + 1, 1) AS rn,
@uid := user_id AS uid,
@mk := meta_key AS mk,
um.*
FROM `user_meta` AS um
CROSS JOIN (SELECT @uid := 0, @mk := 0, @rn := 0) AS i
ORDER BY um.user_id, um.meta_key, um.meta_date DESC
) AS t
WHERE t.rn = 1
) AS r ON u.user_id = r.user_id
WHERE u.user_id = 23