Как выбрать данные?

Запросы, планы, оптимизация запросов, ...

Модераторы: 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
:idea: а что, если автору с 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 писал(а):Тогда вот так:

Код: Выделить всё

select t.* from aa t...
Запрос работает, спору нет. А если усложнить задание, добавив поле ДАТА. Надо выбрать по 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

Ответить