Get the first line for each ID
Today, I would like to get the list of all events of a list which have been selected or have the farest date. I actually use the following code
SELECT choices.id AS id, events.id AS event_id,
events.owner_id, choices.selected,
choices_dates.label AS events_date
FROM events
LEFT JOIN polls ON (events.id = polls.event_id)
LEFT JOIN choices ON (polls.id = choices.poll_id)
LEFT JOIN choices_dates ON (choices.id = choices_dates.choice_id)
WHERE polls.kind = 'date'
ORDER BY events.id, choices.selected DESC, events_date DESC;
I obtain this result :
id event_id owner_id selected events_date
2 1 1 0 2011-04-20 12:00:00
1 1 1 0 2011-04-20 00:00:00
7 2 1 0 2011-04-20 12:00:00
6 2 1 0 2011-04-20 00:00:00
13 3 1 0 2011-04-22 15:57:54
12 3 1 0 2011-04-20 12:00:00
11 3 1 0 2011-04-20 00:00:00
But here is what I want :
id event_id owner_id selected events_date
2 1 1 0 2011-04-20 12:00:00
7 2 1 0 2011-04-20 12:00:00
13 3 1 0 2011-04-22 15:57:54
I can't do nested query because I am creating a VIEW and the group by gives me random results (I obtain the first line for the event_id 1, and the last one for the event_id 2, ...)
For now, I could do the job with php function, but it is not optimisez and my code is dirty.
Does someone have any idea for doing this with a great SQL function ?
Thanks, Kevin
EDIT : I've successeed to do what i want : I've used two different VIEW :
CR开发者_如何学运维EATE VIEWview_events_maxAS SELECT events.id AS event_id, MAX(choices.selected) AS max_selected, MAX(choices_dates.label) AS max_events_date FROM events LEFT JOIN polls ON (events.id = polls.event_id) LEFT JOIN choices ON (polls.id = choices.poll_id) LEFT JOIN choices_dates ON (choices.id = choices_dates.choice_id) WHERE polls.kind = 'date' GROUP BY event_id
AND
CREATE VIEW view_events_correct AS ( SELECT choices.id AS id, events.id AS event_id, events.owner_id, choices.selected, choices_dates.label AS event_date FROM events LEFT JOIN polls ON (events.id = polls.event_id) LEFT JOIN choices ON (polls.id = choices.poll_id) LEFT JOIN choices_dates ON (choices.id = choices_dates.choice_id INNER JOIN view_events_max ON (events.id = view_events_max.event_id AND (choices.selected = 1 OR (choices.selected = view_events_max.max_selected AND choices_dates.label = view_events_max.max_events_date))) )
Thanks everybody for your help, Kevin
I know in Oracle you could use analytic functions to do this. I dont know if there is something similar for mySql...
select id, event_id, owner_id, selected, events_date from (
SELECT choices.id AS id, events.id AS event_id, events.owner_id as owner_id,
choices.selected as selected,
choices_dates.label AS events_date,
max(choices_date.label) over (partition by events.id) as max_events_date
FROM events LEFT JOIN polls ON (events.id = polls.event_id) LEFT JOIN choices ON
(polls.id = choices.poll_id) LEFT JOIN choices_dates ON (choices.id =
choices_dates.choice_id)
WHERE polls.kind = 'date') innerview
where events_date = max_events_date
order by event_id, selected DESC, events_date DESC;
Does something like this (untested, lacking both a description of the schema, and the version of your database software) work?
select choices.id as id
, events.id as event_id
, events.owner_id
, choices.selected
, choices_dates.label as events_date
from
(
SELECT events.id as max_event_id
, max(choices_dates.label) as max_events_date
FROM events
LEFT JOIN polls ON (events.id = polls.event_id)
LEFT JOIN choices ON (polls.id = choices.poll_id)
LEFT JOIN choices_dates ON (choices.id = choices_dates.choice_id)
WHERE polls.kind = 'date'
GROUP BY events.id
)
LEFT JOIN polls ON (events.id = polls.event_id)
LEFT JOIN choices ON (polls.id = choices.poll_id)
LEFT JOIN choices_dates ON (choices.id = choices_dates.choice_id)
where events_date = max_events_date
and events.id = max_event_id
精彩评论