powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Запрос с группировкой
25 сообщений из 57, страница 1 из 3
Запрос с группировкой
    #39589806
SQL_Junior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте. Извините за возможно нубский вопрос.
Не могу понять и найти как добиться такого результата запроса:
Исходная таблица:
namevaluedateJonh410.10.2017David505.07.2017Jonh308.07.2016Lukas702.03.2015David901.06.2014
Результат:
namedateDavid05.07.2017Jonh08.07.2016Lukas02.03.2015
Необходимо сгруппировать по полю name, но выводить только name и date, где в группе значение value минимально
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589821
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_Junior,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
WITH T AS (
  SELECT
    name,
    value,
    date,
    min(value) over(partition by name) as m_value
  FROM MyTable
)
SELECT
  name,
  date
FROM T
WHERE T.value = T.m_value
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589825
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_Junior,

объединением таблицы саму на себя - см. https://stackoverflow.com/a/48325694/976391

PS. жаль, что на оконные функции нельзя ставить условия сразу в том же запросе
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589826
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_Junior, документация по DDL и DML FirebirdSQL здесь . Тебе нужна агрегатная функция Min.
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589828
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

O!

а вот про трюк с CTE я и не подумал, у меня получилось только select .... from (select ... row_number() over...) where row_number = 1
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589834
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
having значение = min(значение)
group by имя, дата

или меня глючит?
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589836
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

глючит, это условия на сами аггрегаты ПОСЛЕ свёртки, а не на отдельные строки, в агрегаты входящие, до свёртки

https://www.w3schools.com/sql/sql_having.asp
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589837
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И соответственно я пытался повесить HAVING на оконный аггрегат - не жрёт-с :-/

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT
 *,
 ROW_NUMBER() OVER (
     PARTITION BY n_order 
     ORDER BY revision DESC
 ) AS rank
FROM TAB1
HAVING /* WHERE */ rank = 1  -- так нигде нельзя, ни Postgress, ни Oracle, ни MS SQL
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589847
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch,

потому что оконные функции можно использовать только в предложениях SELECT и ORDER BY. Для обхода используем derived table или CTE.
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589848
SQL_Junior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответы.
Забыл указать, версия 2.5
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589852
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Это не объяснение, это фиксирование статуса в lawyer speak, а вот почему такой запрет, почему обычные аггрегаты можно, а их же с окнами уже нельзя, по сути, такого объяснения я не знаю.

Кстати, в твоем запросе какой реальный план получается, в один проход или с JOIN'ом ?
У меня такое впечатление, что в MS SQL на самом деле таки разворачивается обратно в само-объединение.
Если кто умеет читать MS SQL-ные планы, подтвердите или поправьте: http://sqlfiddle.com/#!18/ce7cf/2
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589854
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL_JuniorЗабыл указать, версия 2.5

Ariochобъединением таблицы саму на себя - см. https://stackoverflow.com/a/48325694/976391
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589858
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ariochглючит, это условия на сами аггрегаты ПОСЛЕ свёрткиГруппировки.
Но разве это не то, что требуется: сгруппировать по имени и вывести имя, дата с минимальным "значение" в группе?
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589860
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коррелированный запрос считается "соединением самой с собой"?
Код: sql
1.
2.
3.
select name, value, date
  from MyTable t1
  where value = (select first 1 value from MyTable where name = t1.name order by value)
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589863
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WildSery,

такое по ссылке тоже было, но скорость на обычной талице будет хуже.

Сначала ты ее full scan'ом пробегаешь, а потом на КАЖДУЮ строку еще и подзапрос отдельно дёргаешь.

А если таблица большая и в кэш не влазит?
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589867
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

нет, потому что группируются строки целиком, в том числе и дата (считай, что ты на нее вешаешь функцию "выкинуть в окошко")

на выходе из этого запроса у тебя есть
1) индивидуальные значения по столбцам GROUP BY, все или избранные
2) те или иные аггрегаты по остальным столбцам, все или избранные

Если "дата" не входит в 1 - то она входит в 2

Соответственно, с помощью HAVING ты можешь "вычёркивать" строки уже из этого результата, убирать из множества то, что тебе не нужно. Но не добавлять в множество.

В этом запросе значений (индивидуальных) по столбцу "дата" просто изначально нет, и как ты его не уменьшай через HAVING или WHERE - они там уже не появятся.
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589870
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AriochА если таблица большая и в кэш не влазит?
Если, если, ...
Тогда надо дурью не страдать, а делать оптимально
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
declare name_ = '';
for select name, value, date
  from MyTable
  order by name, value
  into ...
do
  if name_ != name then begin
    name_ != name;
    suspend;
  end
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589872
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WildSery,

"А ещё под эту музыку мы можем делать ТАК!"

(С) Масяня
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589873
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ariochнет, потому что группируются строки целиком, в том числе и датаВсё - дошло.
Дата в group by лишняя, но если убрать её из группировки, то нельзя выводить её в результат без какой-либо агрегатной функции, а подходящей агрегатной функции у нас нет.
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589885
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AriochЭто не объяснение, это фиксирование статуса в lawyer speak, а вот почему такой запрет, почему обычные аггрегаты можно, а их же с окнами уже нельзя, по сути, такого объяснения я не знаю.

ответ так описано в SQL стандарте тебя устроит? Я не шучу действительно описано.

Ну троечные планы ты читать научился наверное. Маленький пример

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
with t(a, b, c) as (
  select 1, 2, 1  from rdb$database
  union all
  select 2, 3, 2 from rdb$database
  union all
  select 1, 5, 3 from rdb$database
  union all
  select 2, 4, 4 from rdb$database
),
ag as (
  select
    a,
    b,
    c,
    min(b) over(partition by a) m_b
  from t
)
select
  a,
  c
from ag
where b = m_b



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Select Expression
    -> Filter
        -> Window
            -> Record Buffer (record length: 66)
                -> Sort (record length: 76, key length: 8)
                    -> Window
                        -> Record Buffer (record length: 33)
                            -> Union
                                -> Table "RDB$DATABASE" as "AG T RDB$DATABASE" Full Scan
                                -> Table "RDB$DATABASE" as "AG T RDB$DATABASE" Full Scan
                                -> Table "RDB$DATABASE" as "AG T RDB$DATABASE" Full Scan
                                -> Table "RDB$DATABASE" as "AG T RDB$DATABASE" Full Scan


По плану видно результат буферизируется. Далее сортируется для разделения по группам и вновь буферизируется. После чего проход по буферу окна и фильтрация результатов. Собственно сам скан таблицы происходит однократно. Дальше сортировка и работа с буфером.
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589886
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис, как-то мудрёно...
Почему бы не?:
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT a.name, a.date
  FROM test a
    INNER JOIN (
        SELECT name, Min(value) min_val
          FROM test
          GROUP BY name
      ) b ON b.min_val = a.value AND b.name = a.name
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589888
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, представь, что ты минимумы-максимумы для скорости вынес в отдельную "группировочную" таблицу, и тогда первичная таблица у тебя стала типовой lookup-table.
Это просто две таблицы, разных, и их надо джойнить.

grp payload1 101 202 303 40

сколько строк вернёт
Код: plaintext
Select * from ... where grp = 1
?

a сколько строк вернёт
Код: plaintext
Select min(grp) from ...
?

и как ты хочешь и то и другое в один запрос впрячь ?
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589893
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

чтобы не копипастить почти одинаковый запрос к одной и той же таблице, а обойтись единственным select'ом
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589896
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch"А ещё под эту музыку мы можем делать ТАК!"Неее. Под эту музыку мы можем делать ТАК.
Код: sql
1.
2.
3.
select name, left((min(cast(value as char(10)) || date), 10) value, substring(min(cast(value as char(10)) || date) from 11) date
  from MyTable
  group by name
...
Рейтинг: 0 / 0
Запрос с группировкой
    #39589899
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисответ так описано в SQL стандарте тебя устроит?

нет, конечно, потому что все сервера от стандарта отклоняются, например что-то не смогли реализовать, а что-то наоборот добавили.

например те же select FIRST 10 SKIP 20 * from .... - в стандарте такого нету ( до 2008 вообще, после ИМЕННО такого ), а в FB - есть
...
Рейтинг: 0 / 0
25 сообщений из 57, страница 1 из 3
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Запрос с группировкой
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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