Я использую MySQL и у меня есть две таблицы в форме ниже:
< Сильный > Пользователь :
user_id - user_name - телефон< Сильный > 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";
3 ответа
Вы можете использовать следующее:
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
Демонстрация: https://www.db-fiddle.com/ F / euqvGNW6PguCG495Yi9dTa / 1
Я хочу предложить решение, основанное на использовании ROW_NUMBER функция . Это решение широко используется в других базах данных. Например, посмотрите здесь. Но ваша версия MySQL не поддерживает функцию ROW_NUMBER, и я использовал ее эмуляцию, описанную здесь, Чтобы проверить мое решение, нажмите здесь.
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
Хотя я настоятельно советую против такой реализации, я не буду пытаться передумать. Хотя есть много способов добиться этого, я считаю, что приведенный ниже запрос будет иметь наименьшее снижение производительности (без использования агрегатов).
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 не действует. Поэтому сначала мы выбираем строки и упорядочиваем их по дате desc, после чего группируем. Таким образом, он сохраняет порядок сортировки.
Пожалуйста, ознакомьтесь с рабочим решением здесь, также обратите внимание, что я добавил 2 оператора INDEX CREATE к примеру сценария создания базы данных в левой панели. Это минимум, чтобы обеспечить хоть какую-то адекватную производительность по мере роста базы данных.
Новые вопросы
mysql
MySQL - это бесплатная система управления реляционными базами данных с открытым исходным кодом (RDBMS), использующая язык структурированных запросов (SQL). НЕ ИСПОЛЬЗУЙТЕ этот тег для других БД, таких как SQL Server, SQLite и т. Д. Это разные БД, которые все используют свои собственные диалекты SQL для управления данными.