SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 26.05.2011 14:35:52

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Базовая задача

Столкнулся с задачей, знаю что есть много решений. Как оптимальнее?

Есть две таблицы: Авторы и Книги.
Надо выбрать всех авторов и вывести последнюю книгу для каждого из них.

Результатом должен быть список:
Уникальный автор, его id, id книги и её название.

Подскажите решение.


Похоже я здесь надолго
=8-D

Неактивен

 

#2 26.05.2011 15:11:40

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Базовая задача

SELECT MAX(id), author_id FROM books GROUP BY 2

С ключиком на (author_id, id) может работать быстро и без денормализации.

Неактивен

 

#3 26.05.2011 15:30:05

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: Базовая задача

paulus написал:

SELECT MAX(id), author_id FROM books GROUP BY 2

я так понимаю GROUP BY 2 синоним GROUP BY author_id

это понятный запрос.
значит итоговый запрос будет


SELECT * FROM author
JOIN (SELECT MAX(id), author_id FROM books GROUP BY 2) as t2 ON t2.author_id = author.author_id
 

так?

если авторов много а надо вывести первых 10 по алфавиту, то не будет ли запрос делать лишнюю работу во вложенном запросе?


Вот в чем дело!!! мне надо не MAX(id) а самую последнюю по размещению т.е. ORDER BY date. Сложность в том что GROUP делается до ORDER

Отредактированно AvtoNom (26.05.2011 15:47:29)


Похоже я здесь надолго
=8-D

Неактивен

 

#4 26.05.2011 16:03:38

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Базовая задача

Ну, у Вас же id растут монотонно с датой. Если мое решение не нравится —
выбирайте MAX(date) wink

Если авторов 10, то надо развернуть — сначала искать авторов, а потом
уже для каждого искать книгу.

Неактивен

 

#5 26.05.2011 16:15:03

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: Базовая задача

и как сделать что бы сначала нашли 10 авторов а только потом для них подобрать книги?


Похоже я здесь надолго
=8-D

Неактивен

 

#6 26.05.2011 17:28:42

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: Базовая задача

вот что получилось в моем реальном случае

причем во вложенном запросе ошибку выдавал SQL_CALC_FOUND_ROWS


SELECT object2 . * , MIN( object_pict.sortOrder ) , object_pict.pict
FROM object_pict
JOIN (
SELECT object_id
FROM object
ORDER BY object_id
LIMIT 0 , 10
) AS object2
USING ( object_id )
GROUP BY object_pict.object_id
 


id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
1    PRIMARY    <derived2>    ALL    NULL    NULL    NULL    NULL    10    Using temporary; Using filesort
1    PRIMARY    object_pict    ALL    NULL    NULL    NULL    NULL    366    Using where; Using join buffer
2    DERIVED    object    index    NULL    PRIMARY    4    NULL    10    Using index


SELECT SQL_CALC_FOUND_ROWS object . * , object_pict2.pict
FROM object
JOIN (
SELECT MIN( sortOrder ) , object_pict . *
FROM object_pict
GROUP BY object_id
) AS object_pict2
USING ( object_id )
LIMIT 0 , 10
 



id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
1    PRIMARY    <derived2>    ALL    NULL    NULL    NULL    NULL    74    
1    PRIMARY    object    eq_ref    PRIMARY    PRIMARY    4    object_pict2.object_id    1    Using where
2    DERIVED    object_pict    ALL    NULL    NULL    NULL    NULL    366    Using temporary; Using filesort


Похоже я здесь надолго
=8-D

Неактивен

 

#7 26.05.2011 17:44:08

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: Базовая задача

максимум чего добился


SELECT  object2.*, min(object_pict.sortOrder), object_pict.pict
    from object_pict
    right JOIN (
        SELECT *
        FROM object
        ORDER BY object_id
limit 0,10        
    ) as object2 USING(object_id)
    GROUP BY object_pict.object_id
 



id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
1    PRIMARY    <derived2>    ALL    NULL    NULL    NULL    NULL    10    Using temporary; Using filesort
1    PRIMARY    object_pict    ref    object_id    object_id    5    object2.object_id    5    
2    DERIVED    object    ALL    NULL    NULL    NULL    NULL    104    Using filesort


причем во вложенном запросе ошибку выдавал SQL_CALC_FOUND_ROWS


Похоже я здесь надолго
=8-D

Неактивен

 

#8 26.05.2011 19:13:02

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Базовая задача

А почему не написать простым зависимым запросом?

SELECT author.*, (SELECT name FROM books WHERE author_id = a.id ORDER BY date DESC LIMIT 1)
FROM authors a
ORDER BY name
LIMIT 10

Неактивен

 

#9 27.05.2011 12:52:07

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: Базовая задача

большое спасибо. что то не подумал что так просто сработает! ))

Может кому то де пригодиться:

SELECT object.*, (SELECT pict FROM object_pict WHERE object_id = object.object_id ORDER BY sortOrder DESC LIMIT 1) as pict
FROM object
ORDER BY object_id
LIMIT 0,10


id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
1    PRIMARY    object    ALL    NULL    NULL    NULL    NULL    104    Using filesort
2    DEPENDENT SUBQUERY    object_pict    ref    object_id    object_id    5    astera.object.object_id    5    Using where; Using filesort


Похоже я здесь надолго
=8-D

Неактивен

 

#10 27.05.2011 14:45:45

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: Базовая задача

похожая задача обсуждалась здесь http://www.sql.ru/forum/actualthread.aspx?tid=593211
они там пишут о этом, не могу понять о чем:


select /*здесь придется перечислить все поля таблицы*/
from (
select *, @rn := if(@olddid = DeviceId, @rn + 1, 1) rn, @olddid := DeviceId
from table1, (select @olddid := -1, @rn := 0)t
order by DeviceId, Volume desc) t
where rn = 1
 


Похоже я здесь надолго
=8-D

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson