Sla
|
|
« : 19-08-2010 06:26 » |
|
Есть таблица категорий, есть таблица статей
Нужно выбрать 10 последний статей из каждой категории
1.SELECT cat_name, cat_id FROM cat 2. и потом в цикле делать SELECT * FROM article WHERE cat_id = $cat_id LIMIT 10
задумался... А можно ли это в один запрос впихнуть? типа select article.* from article left join cat on article.cat_id=cat.cat_id order by cat_id
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Sla
|
|
« Ответ #1 : 19-08-2010 06:44 » |
|
мысль в сторону... можно ли в конструкции having использовать вычисления?
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
baldr
|
|
« Ответ #2 : 19-08-2010 08:18 » |
|
Sla, есть правильное, но не работающее решение SELECT article.*, cat.* FROM article, cat WHERE cat.cat_id IN (SELECT c.cat_id FROM cat c WHERE article.cat_id=c.cat_id ORDER BY 1 LIMIT 10) К сожалению, для MySQL < 5.1 вернется ошибка: Error Code: 1235 This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' Источник: http://stackoverflow.com/questions/494974/limiting-an-sql-join
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #3 : 19-08-2010 09:25 » |
|
можно ли в конструкции having использовать вычисления? Так же, как и в where, плюс функции агрегирования.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Sla
|
|
« Ответ #4 : 19-08-2010 09:44 » |
|
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
baldr
|
|
« Ответ #5 : 19-08-2010 11:26 » |
|
Sla, решение в создании временной таблицы? Или дополнительной процедуры? Я так понимаю, нужно было исключительно через select-запросы, причем, желательно, запрос пошустрее.. Что у тебя получилось-то?
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
Sla
|
|
« Ответ #6 : 19-08-2010 11:51 » |
|
я сейчас проверить не могу, интересно посмотреть план запроса, и сравнить скорость выполнения Через курсор (первое что пришло в голову), через динамический запрос (по моей ссылке) и твой пример
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #7 : 19-08-2010 13:52 » |
|
Если я понял правильно, там, по ссылке, предлагают сделать через процедуру. В общем-то, разумный выход без специфичного запроса. Просто перенос логики с клиента на сервер.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
McZim
|
|
« Ответ #8 : 19-08-2010 14:34 » |
|
Просто стало интересно. Решение для Oracle. create table sla_cat(id number, name varchar2(64)) create table sla_art(id number, cat_id number, name varchar2(64))
insert into sla_cat values(1,'first') insert into sla_cat values(2,'second') insert into sla_cat values(3,'third')
insert into sla_art values(1,1,'article1_from_cat1') insert into sla_art values(2,1,'article2_from_cat1') insert into sla_art values(3,1,'article3_from_cat1') insert into sla_art values(4,1,'article4_from_cat1') insert into sla_art values(5,1,'article5_from_cat1') insert into sla_art values(6,1,'article6_from_cat1') insert into sla_art values(7,1,'article7_from_cat1') insert into sla_art values(8,1,'article8_from_cat1') insert into sla_art values(9,1,'article9_from_cat1') insert into sla_art values(10,1,'article10_from_cat1') insert into sla_art values(11,2,'article1_from_cat2') insert into sla_art values(12,2,'article2_from_cat2') insert into sla_art values(13,2,'article3_from_cat2') insert into sla_art values(14,2,'article4_from_cat2') insert into sla_art values(15,3,'article1_from_cat3') insert into sla_art values(16,3,'article2_from_cat3')
select * from SLA_ART a where a.ID in ( select max(a.ID) keep (dense_rank last order by a.ID) over(partition by a.CAT_ID)rn from SLA_ART a ) union select * from SLA_ART a where a.ID in ( select max(a.ID-1) keep (dense_rank last order by a.ID) over(partition by a.CAT_ID)rn from SLA_ART a )
max(a.ID-1) - цифрой управляем насколько старые статьи мы хотим увидеть.
|
|
|
Записан
|
The CBO without stats is like a morning without coffee. (c) T.Kyte.
|
|
|
HandKot
Молодой специалист
Offline
|
|
« Ответ #9 : 20-08-2010 05:01 » |
|
тоже решил попробовать код для MSSQL, применимость для MySQL не знаю --для 2000 select c.cat_name , c.cat_id , a.article_name from @cat C left join @article a on a.cat_id=c.cat_id left join @article a1 on a1.cat_id=c.cat_id and a1.article_name <= a.article_name group by c.cat_name , c.cat_id , a.article_name having count(a1.cat_id) <= 5 --для 2005 и выше --используя CTE ;with mycte(cat_name, cat_id, article_name, rn) as ( select c.cat_name , c.cat_id , a.article_name , row_number() over (partition by c.cat_id order by a.article_name) rn from @cat C left join @article a on a.cat_id=c.cat_id) select * from mycte where rn <= 5
--используя CROSS APPLY select * from @cat C cross apply (select top 5 * from @article a where a.cat_id=c.cat_id) a
|
|
|
Записан
|
I Have Nine Lives You Have One Only THINK!
|
|
|
McZim
|
|
« Ответ #10 : 20-08-2010 08:08 » |
|
Оптимизировал! select results.id, results.cat_id, results.name from ( select a.*, dense_rank() over(partition by a.cat_id order by a.id desc) rnk from SLA_ART a ) results where rnk <= 2
where rnk <= 2 - управляем количеством выводимых статей.
|
|
|
Записан
|
The CBO without stats is like a morning without coffee. (c) T.Kyte.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #11 : 20-08-2010 14:25 » |
|
тоже решил попробовать код для MSSQL, применимость для MySQL не знаю В самом начале baldr приводил элементарное решение, работающее для MS SQL Server. Только вместо limit нужно взять top.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
McZim
|
|
« Ответ #12 : 21-08-2010 14:11 » |
|
Dimka, а планы?
|
|
|
Записан
|
The CBO without stats is like a morning without coffee. (c) T.Kyte.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #13 : 21-08-2010 19:53 » |
|
McZim, план для группировки почти постоянный, план с in-подзапросом прямо зависит от количества отбираемых в подзапросе членов. На небольших N подзапрос лучше группировки, на больших N - наоборот.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
HandKot
Молодой специалист
Offline
|
|
« Ответ #14 : 23-08-2010 04:37 » |
|
Для Dimka думаю, что EXISTS будет быстрее IN
|
|
|
Записан
|
I Have Nine Lives You Have One Only THINK!
|
|
|
McZim
|
|
« Ответ #15 : 23-08-2010 06:50 » |
|
Dimka, я к тому что там используются join, хотя можно обойтись и без него!
|
|
|
Записан
|
The CBO without stats is like a morning without coffee. (c) T.Kyte.
|
|
|
|