2014-01-28 1 views
2

У меня есть то, что можно описать только как кажущуюся простой проблему с вероятным простым решением; но это простое решение ускользает от меня. Я искал и прогуливался по обширной сети StackOverflow только для того, чтобы найти короткие решения только для решения, которые кажутся чрезвычайно сложными. Я уже вид решил эту проблему, но это отвратительно, и мне стыдно за это. Разумеется, есть лучший способ, потому что должен быть Рыцарь в сияющей броне MySQL, владеющий поисковым мечом, который может придумать простое и изящное решение. Вот так:Oh MySQL, как вы присоединяетесь к соответствующим записям по дате

Для этого вопроса мы будем держать эти две таблицы простыми.

Table 1 
users (user_id, active, name) 

и

Table 2 
user_projects (user_project_id, user_id, start_date, details) 

В этом случае записи для пользователей добавляются по мере необходимости. Соответствующие записи затем добавляются, когда проекты завершаются пользователями.

Мой вопрос: Используя запрос, как я могу получить 1 запись, содержащую всю информацию в таблице 1, активных пользователей, присоединившихся к записи из таблицы 2, с самой последней датой на основе start_date?

Другими словами, если у меня есть это:

| user_id | active | name | 
| 1  | 1  | brian | 

и это:

| user_project_id | user_id | start_date | details | 
| 1    | 1  | 2013-10-02 | proj 1 | 
| 2    | 1  | 2013-11-26 | proj 2 | 
| 3    | 1  | 2014-01-02 | proj 3 | 

производит запрос, который дает мне это:

| user_id | active | name | user_project_id | user_id | start_date | details | 
| 1  | 1  | brian | 3    | 1  | 2014-01-02 | proj 3 | 

О, пожалуйста, о, пожалуйста, дайте есть ответ, потому что я обязательно увяжу без него.

+0

Просто быть четко: вы хотите строку для каждого пользователя и их самый последний проект? FYI, вы пытаетесь найти «групповой максимум». (Должен помочь вам Google в будущем).Это можно сделать с помощью одного запроса (как показано ниже), но это может быть очень неэффективным - не бойтесь делать некоторые из обработки кода. – aidan

+0

@aidan, Да. Максимум по группе; Раньше я этого не слышал. Спасибо вам за это. – brian

ответ

3

Поскольку в MySQL есть не такие вещи, как top селекторов, вы можете использовать тройной JOIN, как:

SELECT 
    user_projects.*, 
    users.* 
FROM 
    (SELECT 
    MAX(start_date) AS max_date, 
    user_id 
    FROM 
    user_projects 
    GROUP BY 
    user_id) AS max_dates 
    LEFT JOIN 
    user_projects 
     ON max_dates.max_date=user_projects.start_date 
     AND max_dates.user_id=user_projects.user_id 
    LEFT JOIN 
    users 
     ON users_projects.user_id=users.user_id 
+0

Это правильный ответ и менее сложный, чем то, что я видел и гораздо менее сложный, чем то, что я сделал. Это также самый точный и универсальный. Большое спасибо. – brian

+0

Левое соединение кажется излишним. –

+0

@Jack, этот запрос определенно дал желаемый результат, но мне было бы интересно узнать, можно ли его улучшить. – brian

-1

Вы можете использовать верхний 1 и заказ по дате

select top 1 a.user_id,a.name,b.user_project_id,b.user_id,b.start_date,b.details 
from users a join users_project b on a.user_id = b.user_id 
order by b.start_date desc 

Извините я не уведомление MySQL тег вопрос OP в. Вы можете использовать ключевое слово Limit.

select a.user_id,a.name,b.user_project_id,b.user_id,b.start_date,b.details 
from users a join users_project b on a.user_id = b.user_id 
order by b.start_date desc Limit 1 
+1

В MySQL нет селекторов 'top' –

+0

@AlmaDo Я не согласен с вершиной в моем sql. Я обновил ответ – DevelopmentIsMyPassion

+1

, который вернет только 1 строку. независимо от того, сколько пользователей. –

0
select u1.user_id, u1.name, u.strat_date, u.user_project_id, u.details 
from user_projects u 
left outer join users u1 on u1.user_id=u.user_id 
left outer join 
(select user_id, max(strat_date) as strat_date user_projects group by user_id) as A 
on A.user_id=u.user_id and A.strat_date=u.strat_date 
1

Сначала выберите проекты для каждого пользователя, которые являются самым последним:

SELECT a.* 
FROM user_projects a 
JOIN (
    SELECT user_id, MAX(start_date) AS max_start_date 
    FROM user_projects 
    GROUP BY user_id 
) b ON a.user_id = b.user_id AND a.start_date = b.max_start_date 

Он создает небольшой вспомогательный стол от user_projects включая пользователя и для каждой строки их последней даты проекта; чтобы получить все соответствующие поля таблицы, вы должны присоединиться к этому с помощью user_projects.

Тогда вы просто присоединиться к users с выше результата, чтобы получить окончательный результат:

SELECT * 
FROM users 
JOIN (
    SELECT a.* 
    FROM user_projects a 
    JOIN (
    SELECT user_id, MAX(start_date) AS max_start_date 
    FROM user_projects 
    GROUP BY user_id 
) b ON a.user_id = b.user_id AND a.start_date = b.max_start_date 
) c ON users.user_id = c.user_id 
Смежные вопросы