Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите правильно прописать группировку  [new]
iMerlin
Member

Откуда:
Сообщений: 28
Добрый день, уважаемые коллеги.
Уперся в стену, не знаю даже как правильно сформулировать вопрос гуглю.
Есть задача: получить сгруппированный запрос.
Что бы не перегружать пост огромным и запутанным SELECTом расскажу вкратце: куча таблиц соединяется, к этой куче присоединяется одна таблица трижды (под разными альясами естественно). В этой таблице есть числовые поля, которые надо просуммировать, поле GOD (просто год), поле szap_cat (ссылка на справочник), в той большой куче таблиц тоже есть несколько важных полей, по которым группируем.
Запрос схематично выглядит так:

SELECT
bal_obj.id_bal_obj,...
Sum(zabc.OLD_R) AS oldABCr, Sum(zc2.OLD_R) AS oldC2r, Sum(zzbl.OLD_R) AS oldZBLr,
Sum(zabc.TEK_R) AS ABCr, Sum(zc2.TEK_R) AS C2r, Sum(zzbl.TEK_R) AS ZBLr,
Sum(zabc.Dob_R)AS dobr, Sum(zabc.ptr_R) AS ptrr, Sum(zabc.rzv_r) AS rzvr, Sum(zabc.pc_r) AS pcr, Sum(zabc.spis_r) AS spisr, 
/*перечислили поля, там много, я порезал*/

FROM
ZAP AS zzbl RIGHT JOIN(
	ZAP AS zc2 RIGHT JOIN(
		ZAP AS zabc RIGHT JOIN(
/*...тут еще куча таблиц, я порезал*/
		)ON zabc.id_plast_pi=plast_pi.id_plast_pi And zabc.cat_zap_id=6
	)ON zc2.id_plast_pi=plast_pi.id_plast_pi And zc2.cat_zap_id=4
)ON zzbl.id_plast_pi=plast_pi.id_plast_pi And zzbl.cat_zap_id=39

WHERE 
(
zabc.cat_zap_id=6 OR zabc.cat_zap_id IS NULL) And (zc2.cat_zap_id=4 OR zc2.cat_zap_id IS NULL) And (zzbl.cat_zap_id=39 OR   zzbl.cat_zap_id IS NULL) And  /*тут мы фильтруем по одному из интересующих нас справочников из этой трижды подключенной таблицы, проверка на NULL для того, что бы не потерять записи, в которых присутствуют записи не по всем трем словарным значениям*/
(
/*вот этот блок в скобочках призван объединять только записи по одному году, здесь гдето ошибка и есть, я думаю*/
	(zabc.god= zc2.god And zabc.god=zzbl.god)OR
	(zabc.god IS NULL And zc2.god=zzbl.god)OR
	(zc2.god IS NULL And zabc.god=zzbl.god)OR
	(zzbl.god IS NULL And zabc.god= zc2.god)OR
	(zabc.god IS NULL And zc2.god IS NULL And zzbl.god IS NOT NULL)OR
	(zabc.god IS NULL And zc2.god IS NOT NULL And zzbl.god IS NULL)OR
	(zabc.god IS NOT NULL And zc2.god IS NULL And zzbl.god IS NULL)
)
And BAL_OBJ.ID_BAL_OBJ=320978
GROUP BY sbal_pol_isk.name, bal_obj.name,bal_obj.id_bal_obj, zabc.god,zc2.god,zzbl.god,zc2.god,zzbl.god



В GROUP BY группируем, в частности по году, но так как табличка zap подключена трижды под разными псевдонимами, приходится группировать по трем поля последовательно.

Результат примерно такой (часть полей я отрезал) выборка за 2005 год по одному из объектов.

320978	Ловозерское	2005	NULL	NULL	редкоземельные металлы
320978	Ловозерское	2005	NULL	2005	редкоземельные металлы
320978	Ловозерское	2005	2005	NULL	редкоземельные металлы
320978	Ловозерское	2005	2005	2005	редкоземельные металлы

По всем полям группируется как надо (естественно), а вот по году происходит а-я-яй: все возможные комбинации заполенной графы года с незаполненной.


Уважаемые гуру, подскажите, как правильно построить запрос, чтобы "схлопнуть" эти четыре строки в одну (естественно, с правильным сумиированием числовых полей, чтобы каждая запись в сумму только раз попала).

Хотелось бы без написания программы, так как запрос нужен для контроля правильности переноса данных, а отлаживать и тестировать программу для обработки результата - довольно муторно, да  и хотелось бы более наглядно - одним запросом.


С уважением, Дмитрий.

ps на всякий случай полный текст запроса:

SELECT
bal_obj.id_bal_obj, bal_obj.name,zabc.god,zc2.god,zzbl.god, sbal_pol_isk.name,
Sum(zabc.OLD_R) AS oldABCr, Sum(zc2.OLD_R) AS oldC2r, Sum(zzbl.OLD_R) AS oldZBLr,
Sum(zabc.TEK_R) AS ABCr, Sum(zc2.TEK_R) AS C2r, Sum(zzbl.TEK_R) AS ZBLr,
Sum(zabc.Dob_R)AS dobr, Sum(zabc.ptr_R) AS ptrr, Sum(zabc.rzv_r) AS rzvr, Sum(zabc.pc_r) AS pcr, Sum(zabc.spis_r) AS spisr, Sum(zabc.ism_r) AS ismr,
Sum(zabc.OLD_PK) AS oldABCc, Sum(zc2.OLD_PK) AS oldC2c, Sum(zzbl.OLD_PK) AS oldZBLc,
Sum(zabc.TEK_PK) AS ABCc, Sum(zc2.TEK_PK) AS C2c, Sum(zzbl.TEK_PK) AS ZBLc,
Sum(zabc.Dob_PK)AS dobc, Sum(zabc.ptr_PK) AS ptrc, Sum(zabc.rzv_PK) AS rzvc, Sum(zabc.pc_PK) AS pcc, Sum(zabc.spis_PK) AS spisc, Sum(zabc.ism_PK) AS ismc,
Count(*) cnt


FROM
ZAP AS zzbl RIGHT JOIN(
	ZAP AS zc2 RIGHT JOIN(
		ZAP AS zabc RIGHT JOIN(
			SBAL_POL_ISK INNER JOIN(
				plast_pi INNER JOIN(
					plast_attr INNER JOIN(
						bal_obj INNER JOIN plast ON bal_obj.id_bal_obj=plast.id_BAL_obj
					)ON plast_attr.id_plast=plast.id_plast
				)ON plast_pi.id_plast_attr=plast_attr.id_plast_attr
			)ON SBAL_POL_ISK.ID_sBAL_POL_ISK=plast_pi.id_sbal_pol_isk
		)ON zabc.id_plast_pi=plast_pi.id_plast_pi And zabc.cat_zap_id=6
	)ON zc2.id_plast_pi=plast_pi.id_plast_pi And zc2.cat_zap_id=4
)ON zzbl.id_plast_pi=plast_pi.id_plast_pi And zzbl.cat_zap_id=39

WHERE (zabc.cat_zap_id=6 OR zabc.cat_zap_id IS NULL) And (zc2.cat_zap_id=4 OR zc2.cat_zap_id IS NULL) And (zzbl.cat_zap_id=39 OR zzbl.cat_zap_id IS NULL) And  
(
	(zabc.god= zc2.god And zabc.god=zzbl.god)OR
	(zabc.god IS NULL And zc2.god=zzbl.god)OR
	(zc2.god IS NULL And zabc.god=zzbl.god)OR
	(zzbl.god IS NULL And zabc.god= zc2.god)OR
	(zabc.god IS NULL And zc2.god IS NULL And zzbl.god IS NOT NULL)OR
	(zabc.god IS NULL And zc2.god IS NOT NULL And zzbl.god IS NULL)OR
	(zabc.god IS NOT NULL And zc2.god IS NULL And zzbl.god IS NULL)
)
And BAL_OBJ.ID_BAL_OBJ=320978
GROUP BY sbal_pol_isk.name, bal_obj.name,bal_obj.id_bal_obj, zabc.god,zc2.god,zzbl.god,zc2.god,zzbl.god
ORDER BY bal_obj.id_bal_obj,zabc.god,sbal_pol_isk.name


Сообщение было отредактировано: 4 мар 14, 21:33
4 мар 14, 21:22    [15672751]     Ответить | Цитировать Сообщить модератору
 Re: Помогите правильно прописать группировку  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31438
iMerlin
По всем полям группируется как надо (естественно), а вот по году происходит а-я-яй: все возможные комбинации заполенной графы года с незаполненной.

Уважаемые гуру, подскажите, как правильно построить запрос, чтобы "схлопнуть" эти четыре строки в одну (естественно, с правильным сумиированием числовых полей, чтобы каждая запись в сумму только раз попала).
Нужно группировать по всем полям без агрегатной функции, как вы и делаете.

А вот чтобы "схлопнуть" эти четыре строки в одну, нужно просто выводить не все комдинации года, а один год, то есть вместо:
zabc.god,zc2.god,zzbl.god

напишите:
COALESCE (zabc.god, zc2.god, zzbl.god) as god

И её же поставить в группировку вместо трёх полей.
4 мар 14, 21:50    [15672834]     Ответить | Цитировать Сообщить модератору
 Re: Помогите правильно прописать группировку  [new]
iMerlin
Member

Откуда:
Сообщений: 28
Спасибо за ответ, доберусь до рабочего места сразу проверю, но прошу уточнить:
если я правильно понял MSDN COALESCE возвращает первый ненулевой элемент списка?
Но тогда что будет при отработке записи в которой, допустим, zabc.god=2001, zc2.god=2002, zzbl.god=2003?
Она будет интерпретирована как 2001 и все результаты добавятся к 2001 году?
Или в WHERE оставить блок:
(zabc.god= zc2.god And zabc.god=zzbl.god)OR
(zabc.god IS NULL And zc2.god=zzbl.god)OR
(zc2.god IS NULL And zabc.god=zzbl.god)OR
(zzbl.god IS NULL And zabc.god= zc2.god)OR
(zabc.god IS NULL And zc2.god IS NULL And zzbl.god IS NOT NULL)OR
(zabc.god IS NULL And zc2.god IS NOT NULL And zzbl.god IS NULL)OR
(zabc.god IS NOT NULL And zc2.god IS NULL And zzbl.god IS NULL)
?

Уточните, пожалуйста, чего то совсем не соображу...
5 мар 14, 14:33    [15677132]     Ответить | Цитировать Сообщить модератору
 Re: Помогите правильно прописать группировку  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31438
iMerlin
Но тогда что будет при отработке записи в которой, допустим, zabc.god=2001, zc2.god=2002, zzbl.god=2003?
Такой записи не будет, посмотрите на виши условия в запросе:
(zabc.god= zc2.god And zabc.god=zzbl.god)OR
(zabc.god IS NULL And zc2.god=zzbl.god)OR
(zc2.god IS NULL And zabc.god=zzbl.god)OR
(zzbl.god IS NULL And zabc.god= zc2.god)OR
(zabc.god IS NULL And zc2.god IS NULL And zzbl.god IS NOT NULL)OR
(zabc.god IS NULL And zc2.god IS NOT NULL And zzbl.god IS NULL)OR
(zabc.god IS NOT NULL And zc2.god IS NULL And zzbl.god IS NULL)
5 мар 14, 16:45    [15678223]     Ответить | Цитировать Сообщить модератору
 Re: Помогите правильно прописать группировку  [new]
iMerlin
Member

Откуда:
Сообщений: 28
Ну да ну да, я чего то подумал что от этого можно отказааться, уже потом сообразил.

В общем, все заработало, огромное Вам спасибо. Вот чем отличается профи от самоучки... :-)
5 мар 14, 18:49    [15678984]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить