Запросы, планы, оптимизация запросов, ...
Модераторы: kdv, CyberMax
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 21 дек 2006, 23:52
Привет Всем!
Пусть имеется таблица ID Integer, GroupID Integer.
Как можно выбрать по 5-ть первых записей из каждой группы?
С уважением, Иван.
-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 22 дек 2006, 00:03
в общем случае никак, кроме как процедурой. "первые" существуют только в контексте сортировки, asc или desc. Можно выбрать первые пять, но не "по пять первых".
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 22 дек 2006, 00:35
kdv писал(а):Можно выбрать первые пять, но не "по пять первых".
Я так и думал. Очень жаль...

-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 22 дек 2006, 01:08
Я так и думал. Очень жаль...
наоборот, очень даже здорово. Это ж SQL.
Если ты такой спец по MySQL, приведи пример подобной конструкции.
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 22 дек 2006, 11:21
Код: Выделить всё
select *
from tbl t
where t.id in (select first 5 id from tbl where groupid=t.groupid order by id)
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 22 дек 2006, 11:33
kdv писал(а):Если ты такой спец по MySQL, приведи пример подобной конструкции.
Я не спец по MySQL. Моя специализация FB/Oracle.
А тот вопрос возник по тому, что большинство статей по SQL, с возратом релевантности, написаны для MySQL.
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 22 дек 2006, 11:37
WildSery писал(а):Код: Выделить всё
select *
from tbl t
where t.id in (select first 5 id from tbl where groupid=t.groupid order by id)
Возвращает абсолютно все записи таблицы tbl.
-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 22 дек 2006, 11:51
Возвращает абсолютно все записи таблицы tbl.
об этом написано в release notes. и запрос к тому же неправильный. повторюсь, что такое сделать можно, но только процедурой.
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 22 дек 2006, 12:40
Да? Наверное, пятница сказывается. Не догоняю, что неправильно.
И почему у меня работает?
-
dimitr
- Разработчик Firebird
- Сообщения: 888
- Зарегистрирован: 26 окт 2004, 16:20
Сообщение
dimitr » 22 дек 2006, 14:40
WildSery писал(а):И почему у меня работает?
патамучта FB 2.0
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 22 дек 2006, 15:23
dimitr писал(а):патамучта FB 2.0

а что, если автору с 1.5 перейти на 2.0?
Тогда вопросов "а почему вот у меня в MySQL..." станет меньше.
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 22 дек 2006, 15:34
Тогда вот так:
Код: Выделить всё
select t.*
from aa t
where (select count(1) from aa where groupid=t.groupid and id<t.id)<5
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 23 дек 2006, 12:29
WildSery писал(а):Тогда вот так:
Запрос работает, спору нет. А если усложнить задание, добавив поле ДАТА. Надо выбрать по 5-ть последних записей, отсортированных по полю ДАТА?
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 23 дек 2006, 12:33
WildSery писал(а):Тогда вопросов "а почему вот у меня в MySQL..." станет меньше.
Я не говорил "а вот у меня в MySQL". Я привел запрос из MySQL, потому-что, большинство статей написано именно для MySQL, по крайне мере по "полноценному поиску" в текстовых полях.
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 23 дек 2006, 12:36
WildSery писал(а):а что, если автору с 1.5 перейти на 2.0?
Тогда вопросов "а почему вот у меня в MySQL..." станет меньше.
Последний раз, когда я заходил на sourceforge.net, там еще не было релиза под Винду. Если есть релиз, то в принципе, я ничего против не имею, можно и 2.0.
-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 23 дек 2006, 23:41
Firebird в первую очередь выпускается как раз под эту самую винду, потом под Linux, а уж потом под все остальное.
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 25 дек 2006, 12:29
avenger писал(а):А если усложнить задание, добавив поле ДАТА. Надо выбрать по 5-ть последних записей, отсортированных по полю ДАТА?
На двойке - просто изменить сортировку в подзапросе.
На единичке и полторашке -
Код: Выделить всё
select t.*
from Tbl t
where (select count(1)
from Tbl
where GroupId=t.GroupId and (aDate>t.aDate or aDate=t.aDate and id<t.id))<5
Все эти построения являются развивающими задачками и в реальной жизни неприменимы.
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 25 дек 2006, 17:25
kdv писал(а):об этом написано в release notes.
Читал release notes 1.5.3 не нашел. Мне все таки интересно почему запросы в fb1.5 и fb2.0 возвращают разные результаты?
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 25 дек 2006, 17:27
WildSery писал(а):На двойке - просто изменить сортировку в подзапросе.
Плохо, что план плохой. Если бы по индексам, и не перебирая всю таблицу по 100 раз, можно было применять. А так буду знать, что такое возможно и как это делается.
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 25 дек 2006, 17:44
avenger писал(а):Плохо, что план плохой. Если бы по индексам, и не перебирая всю таблицу по 100 раз, можно было применять. А так буду знать, что такое возможно и как это делается.
Где плохой? На двойке - проще пареной репы, всё за один проход.
Код: Выделить всё
execute block
returns (id int, groupid int, adate date)
as
declare variable grp int;
declare variable cnt int;
begin
grp = -1;
for select id, groupid, adate
from Tbl
order by groupid, adate desc
into id, groupid, adate
do begin
if (groupid != grp) then begin
cnt = 5; grp = groupid;
end
if (cnt > 0) then suspend;
cnt = cnt-1;
end
end