Я знаю, что для некоторых MySQL pro это достаточно просто. Я также понимаю, что ответ, вероятно, можно было бы понять из других ответов, однако я потратил некоторое время на попытку построить этот запрос, и я не могу понять, как применять эти решения к моей ситуации.
Шахта выглядит иначе, чем другие, которые хотят "мин и максимум" поля, но мне нужно значение из другого поля на основе "мин и макс" поля даты.
Учитывая следующую структуру - таблицу "пользователь" и таблицу "записи":
Пример данных (для таблицы "записи"):
id | user_id | date | value
---+---------+--------------+-------
1 1 2018-02-01 125
2 5 2018-01-15 220
3 1 2017-12-31 131
4 4 2018-01-01 77
3 1 2017-12-15 133
Я хотел бы знать значение первой записи (по дате), значение последней записи (по дате) и user_id.
Результаты должны быть следующими:
user_id | first_date | first_value | last_date | last_value
--------+------------+-------------+------------+-----------
1 2017-12-15 133 2018-02-01 125
4 2018-01-01 77 2018-01-01 133
5 2018-01-15 220 2018-01-15 220
Хотя я хочу лучшее решение, то, над чем я работал, вращается вокруг объединения таких запросов:
SELECT user_id, l.date AS last_date, l.value AS last_value, f.date AS first_date, f.value AS first_value
FROM user AS u
LEFT JOIN (SELECT user_id, date, value FROM entries ORDER BY date ASC LIMIT 1) AS f ON f.user_id = u.user_id
LEFT JOIN (SELECT user_id, date, value FROM entries ORDER BY date DESC LIMIT 1) AS l ON l.user_id = u.user_id
ПРИМЕЧАНИЕ. Это не работает. Если бы я захотел "первой записи" для кого-то, я бы написал запрос, который был SELECT user_id, date, value FROM entries ORDER BY date ASC LIMIT 1
- однако использование его в подзапросах не имеет желаемого эффекта.
Я также пробовал некоторые запросы GROUP BY
, но не имел успеха.
SQL Fiddle: http://sqlfiddle.com/#!9/71599
Следующий запрос дает ожидаемый результат, но он выполняется без использования LEFT JOIN
. Таким образом, значения NULL
исключаются.
SELECT
u.id AS user_id,
e1.date AS first_date,
e1.value AS first_value,
e2.date AS last_date,
e2.value AS last_value
FROM
users u,
(SELECT * FROM entries e ORDER BY date ASC) e1,
(SELECT * FROM entries e ORDER BY date DESC) e2
WHERE
e1.user_id = u.id
AND
e2.user_id = u.id
GROUP BY
u.id
И вот рабочая скрипка - http://sqlfiddle.com/#!9/71599/8
Кроме того, стоит отметить, что LIMIT
в вашей попытке ограничит результаты 1 для всех объединенных результатов, а не для каждого объединенного результата. В любом случае, LEFT JOIN
не работает. Если кто-нибудь знает, почему, мне было бы интересно понять.
Edit: Здесь другая попытка, на этот раз с использованием MIN()
и MAX()
, а не ORDER BY
. К сожалению, для этого вам нужно несколько раз присоединиться к таблице entries
.
SELECT
u.id AS user_id,
e1.date AS first_date,
e1.value AS first_value,
e2.date AS last_date,
e2.value AS last_value
FROM users u
INNER JOIN entries e1 ON (u.id = e1.user_id)
INNER JOIN entries e2 ON (u.id = e2.user_id)
INNER JOIN (
SELECT user_id, MIN(date) AS date
FROM entries
GROUP BY user_id
) e3 ON (e1.user_id = e3.user_id AND e1.date = e3.date)
INNER JOIN (
SELECT user_id, MAX(date) AS date
FROM entries
GROUP BY user_id
) e4 ON (e2.user_id = e4.user_id AND e2.date = e4.date)
GROUP BY u.id
Еще одна рабочая скрипка: http://sqlfiddle.com/#!9/71599/18
ORDER BY
в подзапросах. Вернуться к доске для рисования.