Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца? / 25 сообщений из 29, страница 1 из 2
16.08.2018, 17:06
    #39689012
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
FB3. Условный запрос:
Код: sql
1.
2.
3.
select t.value, t.edate
from t
order by 1, 2 desc


Для каждой value есть десятки/сотни edate. Нужно для каждой value ограничить количество выдаваемых edate, например, десятью. Если записей для конкретного value меньше десяти, то выдать сколько есть. Возможно? Посмотрел оконные функции, first, fetch, ничего подходящего не нахожу. Хранимку не хотелось бы. Execute block, for select...do устроили бы.
...
Рейтинг: 0 / 0
16.08.2018, 17:07
    #39689014
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Как-то так: select from select group by having
...
Рейтинг: 0 / 0
16.08.2018, 17:12
    #39689016
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
windows functions -> row number partition by t.value

KreatorXXIдля каждой value ограничить количество выдаваемых edate, например, десятью

количество чего конкретно - строк в группе value вообще, или же уникальных значений edate (может быть у тебя будет всего лишь родно edate, но сто строк с ним) ?
...
Рейтинг: 0 / 0
16.08.2018, 17:14
    #39689019
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
за основу посмотри тут: http://www.sql.ru/forum/1283351/zapros-s-gruppirovkoy

но там я брал не десять строк, а только одну
...
Рейтинг: 0 / 0
16.08.2018, 17:50
    #39689045
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Arioch,

спасибо за наводку. Типа того:
Код: sql
1.
2.
3.
4.
select t.value, t.edate,
         row_number() over (partition by t.value order by t.edate desc)
from t
order by 1, 2 desc


Потом select from select или CTE.
Кстати, в руководстве по языку по оконным функциям похоже нет ни одного примера с одновременным использованием partition by и order by. Что меня и выбило из колеи. Чувствую, что решение где-то здесь...
...
Рейтинг: 0 / 0
16.08.2018, 17:57
    #39689050
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXIКстати, в руководстве по языку по оконным функциям похоже нет ни одного примера с одновременным использованием partition by и order by.

Упс... Добавлю. Оно есть но только в доке по 4.0, и не в явном виде, когда рассказывается уже про именованные окна
...
Рейтинг: 0 / 0
16.08.2018, 18:03
    #39689054
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXIПосмотрел оконные функции, first, fetch, ничего подходящего не нахожу.Значит, плохо смотрел. Строки нумеровать в группе плёвое дело.
KreatorXXIExecute block, for select...do устроили бы.Тоже элементарно. Вложенный for select, пожалуй, будет оптимально, поскольку его легче прервать, когда "хватит".
...
Рейтинг: 0 / 0
16.08.2018, 18:04
    #39689055
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

кстати для понимания как работают оконные функции лучше читать доку по 4.0. В ней рассказывается об одной очень важной части оконных функций (рамки окна), явное задание которой не реализована в 3.0.
...
Рейтинг: 0 / 0
16.08.2018, 18:46
    #39689082
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Ariochза основу посмотри тут: http://www.sql.ru/forum/1283351/zapros-s-gruppirovkoy

этот топик бы вообще "приклеить" в начале форума, именно потому что там обсуждались оконные функции в деталях и на полезном для жизни примере
...
Рейтинг: 0 / 0
17.08.2018, 10:17
    #39689287
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
За ночь всё же пришло понимание, что не совсем хорошо. Результат правильный, но записи-то все просматриваются. Не есть хорошо. В текущей базе по времени всё классно. Но в будущем надо будет пересмотреть. Кроме как использовать lateral join на ум ничего не приходит. Нет, ещё можно попробовать циклы for select с явным выходом из них. Ни сердце ни душа к этому не лежит.
...
Рейтинг: 0 / 0
17.08.2018, 11:26
    #39689356
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

ну так. Понимать надо что для работы оконных функций требуется буферизация, причём всей выборки целиком, предикаты на CTE не будут прокинуты в окно.
...
Рейтинг: 0 / 0
17.08.2018, 11:39
    #39689368
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
WildSeryВложенный for select, пожалуй, будет оптимально, поскольку его легче прервать, когда "хватит".

а вот это не факт. Это сильно зависит от индексов и распределения значений. Иногда full scan сделать дешевле, чем сначала группировку по полю (индекса может и не быть), потом снова выборку по сгруппированному полю + к ещё и сортировку по другому полю.
...
Рейтинг: 0 / 0
17.08.2018, 11:40
    #39689369
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Симонов Денис,

фильтр по row_number в принципе можно бы было и прокидывать сверху вниз, внутрь окна
...
Рейтинг: 0 / 0
17.08.2018, 11:52
    #39689381
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Симонов Денис,

да, я всё понимаю, к оконным функциям претензий нет. Просто хотелось ещё плюсом поиметь сокращение "фетчей". Идея такая. Отказаться от оконных функций, а сделать типа такого:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select t1.value, t3.edate
from t1
     lateral join (
                    select first 10 t2.edate
                    from t2
                    where t2.t1_id = t1.t1_id
                    order by t2.edate desc
                  ) t3 on true
where t1....


Или нереально придумал?
...
Рейтинг: 0 / 0
17.08.2018, 11:56
    #39689390
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Arioch,

там много специфики, которая оптимизатором не учтена.

row_number требует сортировки результата, по уму работает только с предложением ORDER BY внутри окна. Сортировка там доступна только планом SORT, т.е. без использования навигации по индексу (ORDER INDEX), потому что могут быть секции заданные PARTITION BY, а может и не быть. Как известно сортировка SORT требует полный фетч. Сам по себе PARTITION BY то же требует сортировки, причём опять же поддерживается только SORT. Не уверен что это можно легко разрулить.

Прокидывание предикатов по полям в PARTITION BY может быть сделана безболезненно, но это только если у нас ровно одно окно или несколько, но с одинаковыми PARTITION BY.

Надо понимать что оконные функции не панацея. В некоторых случаях они значительно могут облегчить жизнь, но не следует их пихать во все щели. По большому счёту они полезны в различных отчётах, но делать с ними живые выборки быстро возвращающие результат не следует.
...
Рейтинг: 0 / 0
17.08.2018, 12:05
    #39689399
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

если разработчики будут успевать по срокам lateral join будет в 4.0. Но опять же не факт что в данном случае это будет быстрее. Группировка один фиг требует полного сканирования будь оно сделано NATURAL с сортировкой, или с помощью ORDER INDEX. В первом случае и так будет буферизация, о втором может работать поточно, но полная выборка может потребовать больше чтений с диска (если выборка реально большая). А потом всему этому будет выполняться второй запрос со своим оверхедом. В общем мерить надо. Может получиться дешевле, а может и дороже. Однозначно утверждать что лучше я бы не стал.
...
Рейтинг: 0 / 0
17.08.2018, 16:04
    #39689561
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Симонов Денис,

подождём, посмотрим. Сейчас конструкция first вроде не сканирует всё. Естественно, при наличии правильного индекса. Поэтому можно ожидать хорошего быстродействия приведённого мной запроса.
...
Рейтинг: 0 / 0
17.08.2018, 16:11
    #39689568
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXIСейчас конструкция first вроде не сканирует всё. Естественно, при наличии правильного индекса.

это да, но ты не учитываешь затраты на запрос верхнего уровня в котором есть группировка, и потом дополнительный оверхэд на выборку 10 значений edate для каждого value

Проведи уже эксперимент что быстрее.
...
Рейтинг: 0 / 0
20.08.2018, 11:24
    #39690302
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
Симонов Денис,

Не понял какой эксперимент нужен. Если говорить о том, что сейчас есть (select ... from select ...), то время тратится только на "внутренний" select. Внешний фактически не даёт никакого вклада. А вот с lateral join посмотрим потом. Или в снапшот-сборке четвёрки уже есть lateral join?
...
Рейтинг: 0 / 0
20.08.2018, 11:28
    #39690305
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

Денис не верит, что верхний запрос, получающий группировки, дешёвый.
...
Рейтинг: 0 / 0
20.08.2018, 12:12
    #39690328
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
WildSery,

А как доказать? Собственно, в верхнем нет группировки, там только фильтр по значению row_number. Какое-то недопонимание.
...
Рейтинг: 0 / 0
20.08.2018, 12:36
    #39690343
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

Я уже потерял нить ваших рассуждений. Но вроде так:
Для select from select "верхним" называют "внешний", который будет группировать по value и edate, а "внутренний" уже будет для этих
значений отбирать требуемые максимум 10 записей в каждой группировке.
...
Рейтинг: 0 / 0
20.08.2018, 14:43
    #39690445
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

нет lateral join ещё не делали. Если без него то запрос переписывается примерно так

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
execute block 
rerurns (
  value type of column t.value,
  edate type of column t.edate
)
as
begin
  for select value
       from t
       group by value
       order by value desc
       into :value
  do 
  begin
    for select edate
         from t
         where value = :value
         order by edate desc
         fetch first 10 rows only
         into :edate
    do suspend;
  end
end



так вот. Запрос

Код: sql
1.
2.
3.
4.
select value
from t
group by value
order by value desc



может быть совсем не дешёвым и всё равно делать полный скан таблицы, если так, то разницы с оконными функциями не будет, скорее наоборот блок будет проигрывать. Плюс надо смотреть какой там план у внутреннего запроса, он тоже может быть не очень хорошим
...
Рейтинг: 0 / 0
20.08.2018, 14:52
    #39690452
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
WildSery,

Вот так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select v, e 
from (
select t1.value v, t2.edate e,
         row_number() over (partition by t1.value order by t2.edate desc) r
from t1
       inner join t2 on t2.t1_id = t1.t1_id  
order by 1, 2 desc
)
where r<=10



Я так понимаю, внутренний и отбирает и группирует и сортирует. А во внешнем только фильтр.
...
Рейтинг: 0 / 0
20.08.2018, 14:59
    #39690463
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца?
KreatorXXI,

а вот быстрый вариант, но при определённых условиях будет примерно тоже самое что с оконными функциями

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
execute block 
rerurns (
  value type of column t.value,
  edate type of column t.edate
)
as
declare old_value type of column t.value;
declare n integer;
begin
  n = 0;
  old_value = null;
  for select value, edate
       from t
       order by value desc, edate desc
       into :value, edate
  do 
  begin
    if (value distinct from old_value) then
    begin
      old_value = value;
      n = 0;
    end  
    n = n + 1;
    if (n <= 10) then
      suspend;
  end
end



заметь full scan всё равно будет, но возможно немного можно выиграть на сортировке
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как в запросе ограничить количество выдаваемых строк в зависимости от значения столбца? / 25 сообщений из 29, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]