powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Группировка по имени, фамилии.... не нравится мне это
15 сообщений из 15, страница 1 из 1
Группировка по имени, фамилии.... не нравится мне это
    #38608994
Cane Cat Fisher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос по эстетике запросов. В упрощенном виде ситуация такая:

Есть таблица клиентов - CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, к ней справочник - скажем, улицы, STREET_ID, STREET_NAME.

И есть таблица платежей клиента PAY, по одному клиенту много платежей - PAY_ID, CLIENT_ID, PAY_SUM....

Надо получить результат запроса в виде: данные клиента (CLIENT_ID, CLIENT_NAME, всякиеданные, в том числе из справочников - STREET_NAME...), и сумму всех его платежей.

В чужом проекте это решается так:

Код: sql
1.
2.
3.
select CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, STREET_NAME, sum(PAY_SUM) 
  from CLIENT, STREET, PAY...--понятно, по ключам связано
gropup by CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, STREET_NAME -- короче, здесь перечислено все, кроме PAY_SUM.



Как-то меня коробит этот зоопарк в GROUP BY. Я больше люблю, чтобы там были только ключевые поля. Я бы, наверное, извлекал данные из PAY подзапросом в составе селекта из CLIENT, или вообще джоинил разные запросы из CLIENT и из PAY.

Это имеет какое-то основание, или я зря заморачиваюсь, и все нормально делают кучу всего в GROUP BY?
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38609200
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cane Cat FisherВопрос по эстетике запросов
...

Код: sql
1.
2.
3.
select CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, STREET_NAME, sum(PAY_SUM) 
  from CLIENT, STREET, PAY...--понятно, по ключам связано
gropup by CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, STREET_NAME -- короче, здесь перечислено все, кроме PAY_SUM

Как-то меня коробит этот зоопарк в GROUP BY. Я больше люблю, чтобы там были только ключевые поля. Я бы, наверное, извлекал данные из PAY подзапросом в составе селекта из CLIENT, или вообще джоинил разные запросы из CLIENT и из PAY.

Это имеет какое-то основание, или я зря заморачиваюсь, и все нормально делают кучу всего в GROUP BY?Эстетика тут не причем. Делать так можно только от лени, плохая практика. Группировка по куче полей, включая символные даёт неплохой оверхид и может "убить" производительность очень сильно, особенно если такой запрос включается в другой запрос в качестве подзапроса. Лучше избегать подобного способа и групировать только по необходимым полям, дополнительно сливая результат с нужными таблицами для получения остальной информации. Как правило, это работает значительно быстрее, несмотря на дополнительные слияния.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38609305
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cane Cat FisherКак-то меня коробит этот зоопарк в GROUP BY. Я больше люблю, чтобы там были только ключевые поля. Я бы, наверное, извлекал данные из PAY подзапросом в составе селекта из CLIENT, или вообще джоинил разные запросы из CLIENT и из PAY.

Это имеет какое-то основание, или я зря заморачиваюсь, и все нормально делают кучу всего в GROUP BY?Я бы тоже группировал в подзапросе.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38609614
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как-то меня коробит этот зоопарк в GROUP BY.


В принципе, это НОРМАЛЬНАЯ ПРАКТИКА.
Запрос по-другому в нормальных СУБД не заработает.


Я больше люблю, чтобы там были только ключевые поля. Я бы, наверное, извлекал данные из PAY подзапросом в составе селекта из CLIENT, или вообще джоинил разные запросы из CLIENT и из PAY.

Если любишь, сделай группировку сначала по ключевым полям в подзапросе во FROM, а потом JOIN-и справочник клиентов и его дочерние к нему. И тот, и другой вариант запроса возможны, и они равнозначно имеют право на существование -- ни по производительности, ни по другим критериям нет резона не использовать один а не другой.

Хотя -- некоторые СУБД не позволяют использовать подзапросы во FROM. Тогда -- только тот первый вариант, который тебе не нравится.

Это имеет какое-то основание, или я зря заморачиваюсь, и все нормально делают кучу всего в GROUP BY?

Практически не имеет. Есть на самом деле только один решительный довод ЗА твою точку зрения -- в СУБД суммарный размер ключей в GROUP BY может быть ограничен, и тогда твой вариант решения будет оправдан.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38609626
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Группировка по куче полей, включая символные даёт неплохой оверхид и может "убить" производительность очень сильно, особенно если такой запрос включается в другой запрос в качестве подзапроса. Лучше избегать подобного способа и групировать только по необходимым полям, дополнительно сливая результат с нужными таблицами для получения остальной информации. Как правило, это работает значительно быстрее, несмотря на дополнительные слияния.


Да ладно. Нормальный оптимизатор запросто может сделать оптимизацию и убрать из группировки лишние поля и переставить JOIN-ы после группировки.

Даже если это не будет сделано, накладуха там не большая -- только лишние сравнения текстовых полей. Это не дополнительные чтения.

Ну и вообще говорить, что какие-то конструкции SQL заранее обречены на плохую производительность -- плохая идея. Данные, запрос, план, анализ -- тогда да, можно сказать, что так плохо, а так было бы лучше.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38609827
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivДа ладно. Нормальный оптимизатор запросто может сделать оптимизацию и убрать из группировки лишние поля и переставить JOIN-ы после группировки.

Даже если это не будет сделано, накладуха там не большая -- только лишние сравнения текстовых полей. Это не дополнительные чтения.

Ну и вообще говорить, что какие-то конструкции SQL заранее обречены на плохую производительность -- плохая идея. Данные, запрос, план, анализ -- тогда да, можно сказать, что так плохо, а так было бы лучше.Не встречал таких оптимизаторов, которые в такой ситуации догадались бы убирать из группировки лишние поля с перестановкой джойнов. Это где такие ?

"Накладуха" большая, по опыту, встречался с такими конструкциями неоднократно от разных авторов, "гробили" производительность на раз. Сравнение текстовых данных, тем более произвольной длины всегда приводят к излишним потерям на CPU. Чтения чтениям тоже рознь, физические против логических, хотя плохи и те, и другие, но первые значительно хуже.

Можно, когда изучил много планов, то часто достаточно взгляда на конструкцию, которая может стать проблемой. Даже для самого продвинутого оптимизатора.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38610665
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChA,

В субд накладные расходу в CPU - всегда более низших порядков, чем io.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611376
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivВ субд накладные расходу в CPU - всегда более низших порядков, чем io.Естественно, но и не надо их считать уж вовсе ничтожными. При сравнениях символьных полей переменной длины и определённых видах сортировки это время сильно растёт с ростом объема обрабатываемых данных. Уверен, что наблюдали этот процесс и сами. Стоимость IO критична только если все данные при обработке не вмещаются в RAM, а при логических операциях чтения она сравнима с затратами на CPU. Так что соотношение начинает сильно смещаться в его сторону.

Так у какой РСУБД настолько продвинутый оптимизатор, который в упомянутой выше ситуации догадался бы сам убирать из группировки лишние поля с перестановкой джойнов ? Может и правда настало время менять "лошадей" ?
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611446
Кот Матроскин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChA,

MSSQL, кстати, умеет - действительно, не бином ньютона определить, что если в GROUP BY есть первичный ключ таблицы, то остальные поля этой таблицы можно смело оттуда выкидывать.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611537
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кот МатроскинChA,

MSSQL, кстати, умеет - действительно, не бином ньютона определить, что если в GROUP BY есть первичный ключ таблицы, то остальные поля этой таблицы можно смело оттуда выкидывать.

ну вот и в пж такое послабление "с недавних" есть на GROUP BY pk
http://www.sql.ru/forum/1054408/neozhidannoe-povedenie-group-by-pkey?mid=15010843&hl=group primary key#15010843

хотя для задачи автора у меня шаблон: сгруппировать голые ключи, а результат агрегации заджойнить на выборки значимых полей. Обычно дешевле (если не на коленки сиюсекундную выборку писать).
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611546
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кот Матроскинне бином ньютона определить, что если в GROUP BY есть первичный ключ таблицы, то остальные поля этой таблицы можно смело оттуда выкидывать.Я это как бы и не оспариваю, это очевидно. Мнея интересовало, какая из РСУБД это умеет делать.Кот МатроскинMSSQL, кстати, умеетВот простейший пример, ничего лишнего(MS SQL 2008 R2 не слишком стар, надеюсь ?)
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT
	ap.[Data] AS С
	, COUNT(*) AS Cnt
FROM [JhOP.Provodka] op
INNER JOIN [JHProv.DebetID] pr ON (pr.[ObjectID] = op.[ItemID])
INNER JOIN [AAP.Code] ap ON (ap.[ObjectID] = pr.[Data])
GROUP BY ap.[Data]


План
____________________________________________________________
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  |--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[globalagg1012],0)))
       |--Stream Aggregate(GROUP BY:([n].[dbo].[StringA].[Data]) DEFINE:([globalagg1012]=SUM([partialagg1011])))
            |--Sort(ORDER BY:([n].[dbo].[StringA].[Data] ASC))
                 |--Merge Join(Inner Join, MERGE:([n].[dbo].[Reference].[Data])=([n].[dbo].[StringA].[ObjectID]), RESIDUAL:([n].[dbo].[StringA].[ObjectID]=[n].[dbo].[Reference].[Data]))
                      |--Sort(ORDER BY:([n].[dbo].[Reference].[Data] ASC))
                      |    |--Hash Match(Aggregate, HASH:([n].[dbo].[Reference].[Data]) DEFINE:([partialagg1011]=COUNT(*)))
                      |         |--Hash Match(Inner Join, HASH:([n].[dbo].[Reference].[ObjectID])=([n].[dbo].[Items].[ItemID]))
                      |              |--Index Seek(OBJECT:([n].[dbo].[Reference].[ReferenceMain]), SEEK:([n].[dbo].[Reference].[ClassID]=(-30002) AND [n].[dbo].[Reference].[PropertyID]=(2)) ORDERED FORWARD)
                      |              |--Clustered Index Seek(OBJECT:([n].[dbo].[Items].[PropertyItemsFK]), SEEK:([n].[dbo].[Items].[ClassID]=(-30011) AND [n].[dbo].[Items].[PropertyID]=(9)) ORDERED FORWARD)
                      |--Clustered Index Seek(OBJECT:([n].[dbo].[StringA].[PropertyStringAFK]), SEEK:([n].[dbo].[StringA].[ClassID]=(-29897) AND [n].[dbo].[StringA].[PropertyID]=(1)) ORDERED FORWARD)
____________________________________________________________

Как мы видим, не выбрасывает, более того, добавляет Sort, чтобы выполнить "Stream Aggregate". Хотя зачем, собственно, по идее, дальше "Merge Join" выполнять уже не надо, результат уже получен. Хотя, признаю, что COUNT выполнен только по pr.[Data], честь ему и хвала, не стоят на месте, простейшие случаи уже понимают.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611564
Кот Матроскин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChA,

Ничего не понял. Какое отношение этот пример имеет к заглавному сообщению?

Я говорил про то, что при конструкции
Код: sql
1.
group by t.ID, t.Name


оптимизатор сообразит выкинуть Name и группировать только по первичному ключу ID.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611663
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кот Матроскинпри конструкции
Код: sql
1.
group by t.ID, t.Name

оптимизатор сообразит выкинуть Name и группировать только по первичному ключу ID.Так он, в принципе, сумел, только зачем-то начал делать сортировку и аггрегирование потока, что по любому, было излишне. Впрочем неважно, я согласен, что оптимизатор MS SQL Server 2008 R2 уже достаточно продвинут, чтобы понимать такую ситуацию в простых случаях. MS SQL Server 2000, например, даже по вашей конструкции, с добавлением идентификатора выполняет дополнительную сортировку и аггрегирование потока по символьному полю.
Никогда не включал в группировку никаких полей, кроме действительно нужных, возможно пора менять старые привычки и больше доверять оптимизатору, время покажет.
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38611847
Фотография ssas12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cane Cat FisherВопрос по эстетике запросов. В упрощенном виде ситуация такая:

Есть таблица клиентов - CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, к ней справочник - скажем, улицы, STREET_ID, STREET_NAME.

И есть таблица платежей клиента PAY, по одному клиенту много платежей - PAY_ID, CLIENT_ID, PAY_SUM....

Надо получить результат запроса в виде: данные клиента (CLIENT_ID, CLIENT_NAME, всякиеданные, в том числе из справочников - STREET_NAME...), и сумму всех его платежей.

В чужом проекте это решается так:

Код: sql
1.
2.
3.
select CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, STREET_NAME, sum(PAY_SUM) 
  from CLIENT, STREET, PAY...--понятно, по ключам связано
gropup by CLIENT_ID, CLIENT_NAME, ВСЯКИЕ_ДАННЫЕ, STREET_NAME -- короче, здесь перечислено все, кроме PAY_SUM.



Как-то меня коробит этот зоопарк в GROUP BY. Я больше люблю, чтобы там были только ключевые поля. Я бы, наверное, извлекал данные из PAY подзапросом в составе селекта из CLIENT, или вообще джоинил разные запросы из CLIENT и из PAY.

Это имеет какое-то основание, или я зря заморачиваюсь, и все нормально делают кучу всего в GROUP BY?


GROUP BY по 20-ти- 30-полям?
да на каком ЕГЭ/ВУЗе учат собирать всё и вся в одну широкую простыню?
какая-то тотальная шизА в конторах.
СБ куда смотрит за такие выборки
...
Рейтинг: 0 / 0
Группировка по имени, фамилии.... не нравится мне это
    #38612529
movingshadow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Cane Cat Fisher,

А если через CTE?

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
;WITH [Pay_Sum]
AS
(
SELECT
   CLIENT_ID,
   SUM(PAY_SUM) AS [Amount]
FROM
   PAY
GROUP BY
   CLIENT_ID
)
SELECT
   CLIENT.*, --Все поля клиента
   [Pay_Sum].[Amount] --Итого по клиенту
FROM
   CLIENT
LEFT JOIN
   [Pay_Sum]
      ON [Pay_Sum].CLIENT_ID = CLIENT.CLIENT_ID
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Группировка по имени, фамилии.... не нравится мне это
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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