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

Откуда: Питер
Сообщений: 63
Добрый день, имеется старый запрос вида
select id, name, avg(sum) from dbo.order
where order_date between @start_date and @end_date
group by id, name


Появилась задача выводить не "среднее в общем", а "среднее за год", "среднее за день", "среднее за месяц", то есть по факту, тупо менять последнюю строку запроса на, допустим
group by id, name [, year(order_date) [,month(order_date) [,day(order_date)]]]
, а в выводе добавить атрибут вида
concat('',[day][,month][,year],'') as gval
(В квадраных скобках, как всегда, опциональные атрибуты)


Понятно, что это элементарно делается в любом языке программирования, ведь там запрос - просто текстовая переменная. И понятно, что формально это не один меняющийся запрос, а четыре разных, однако они настолько однотипны по виду и по выводу, что мой больной мозг прямо-таки просит их как-то "запихать в один".

Собственно вопросы:
1) Возможно ли такое сделать средствами SQL, например через хранимую процедуру? (тут вроде препятсятвий нет, уже представляю, как именно это делать)
1а) В самой хранимой процедуре мне придестя писать 4 разных запроса или можно "извернуться" и сделать один, "динамический"?
2) Не является ли написание такой хранимой процедуры примером "кода с запашком" (переводя на русский - "правильнее" написать 4 процедуры/запроса, а не "один универсальный")
9 окт 15, 13:09    [18258285]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Shakill
Member

Откуда: мск
Сообщений: 1880
Kotetsu, в секции group by можно использовать case
9 окт 15, 13:13    [18258309]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20609
Kotetsu
мой больной мозг прямо-таки просит их как-то "запихать в один"

Срочно лечите мозг. Запросы, у которых различается структура выходного набора, НЕЛЬЗЯ объединять.
9 окт 15, 13:20    [18258356]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Glory
Member

Откуда:
Сообщений: 104760
select id, name, avg(sum) from dbo.order
where order_date between @start_date and @end_date
group by id, name, <year>, <month>, <day> with rollup
where <здесь можно использовать фильтр по GROUPING() для получения только нужных строк>
9 окт 15, 13:26    [18258415]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 9413
declare @PeriodType varchar(10)

select
 t.p, avg(o.sum)
from
 dbo.order o cross apply
 (select isnull(left(convert(varchar(8), o.order_date, 112), case @PeriodType when 'Год' then 4 when 'Месяц' then 6 when 'День' then 8 end), '')) t(p)
where
 o.order_date between @start_date and @end_date
group by
 t.p;
9 окт 15, 13:50    [18258603]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Glory,

WHERE после GROUP BY?
Наверно, HAVING?
9 окт 15, 13:55    [18258637]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Kotetsu
Member

Откуда: Питер
Сообщений: 63
Akina,
Структура у них как раз идентична.

Id, name, avg, gval

где
gval = concat('',case when @day_gr_needed then (<day> + '.'), case when (@day_gr_needed or @month_gr_needed) then ...
.

То есть по выводу они будут отличаться только количеством строк при разных группировках и тем, как выглядят данные в колонке "grval" - '01.02.2015', '02.2015', '2015' или ''. Обработка результатов в любом случае будет на стороне приложения.

Хотелось иметь одну хранимую процедуру, а не кучу (чем больше процедур, тем легче в них запутаться. А уж про то, какой ад править 4 процедуры вместо одной - вообще лучше не говорить).

Shakill, Glory - большое спасибо, попробую оба метода.
9 окт 15, 13:57    [18258650]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Glory
Member

Откуда:
Сообщений: 104760
Kotetsu
Хотелось иметь одну хранимую процедуру, а не кучу (чем больше процедур, тем легче в них запутаться. А уж про то, какой ад править 4 процедуры вместо одной - вообще лучше не говорить).

Ага лучше иметь одну универсальную процедуру, выполняющую вообще все, что можно
9 окт 15, 14:01    [18258676]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Kotetsu
Member

Откуда: Питер
Сообщений: 63
Glory
Kotetsu
Хотелось иметь одну хранимую процедуру, а не кучу (чем больше процедур, тем легче в них запутаться. А уж про то, какой ад править 4 процедуры вместо одной - вообще лучше не говорить).

Ага лучше иметь одну универсальную процедуру, выполняющую вообще все, что можно


Ну совсем уж все - невозможно. У меня желание объединить из-за того, что долго били по голове - "количество абсолютно идентичного или почти идентичного кода должно быть минимально" и заставляли такой код безжалотно рефакторить. А теперь я не могу иначе. Устойчивая аллергия на код, который можно заподозрить в "Ctrl-C, Ctrl-V"
9 окт 15, 14:45    [18258988]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20609
Kotetsu
Структура у них как раз идентична.

То есть только я один вижу, что нужно
Kotetsu
в выводе добавить атрибут вида
concat('',[day][,month][,year],'') as gval

???
9 окт 15, 15:10    [18259125]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31444
Kotetsu
У меня желание объединить из-за того, что долго били по голове - "количество абсолютно идентичного или почти идентичного кода должно быть минимально" и заставляли такой код безжалотно рефакторить. А теперь я не могу иначе. Устойчивая аллергия на код, который можно заподозрить в "Ctrl-C, Ctrl-V"
Увы, T-SQL для этого плохо приспособлен. Модульность, библиотеки, функции, пространства имён, передачи параметров - всё это не про него. Всё в самом зачаточном состоянии.
Из положения иногда выходят, переходя на языки-надстройки. Либо делают свои языки, либо по простому прогоняют код через С-шний прекомпайлер.
Но это подходы не для обычной разработки, это для неких крупных систем, типа 1С или САП.
9 окт 15, 15:13    [18259139]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
Akina
Kotetsu
Структура у них как раз идентична.

То есть только я один вижу, что нужно
Kotetsu
в выводе добавить атрибут вида
concat('',[day][,month][,year],'') as gval

???

Думаю, все это видят, просто для случая группировки всего (без годов/месяцев/дней) можно туда вывести null - и тогда структура будет идентична.
9 окт 15, 15:21    [18259173]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20609
Minamoto
для случая группировки всего (без годов/месяцев/дней) можно туда вывести null

Я догадываюсь, что можно сделать дофига чего, чтобы не оказаться где не надо. Но структура исходного запроса - зафиксирована. И в случае таких доработок она изменится. Что может привести к нежелательным последствиям.

+
Представь себе, что ты проделал указанные действия. Но не знаешь, что где-то этот запрос используется как источник данных, и для неких целей отдельные поля сливаются конкатенацией. Что ты получишь вместо данных?
9 окт 15, 17:21    [18259905]     Ответить | Цитировать Сообщить модератору
 Re: Надстройка над уже существующим запросом  [new]
Kotetsu
Member

Откуда: Питер
Сообщений: 63
Minamoto
Akina
пропущено...

То есть только я один вижу, что нужно
пропущено...

???

Думаю, все это видят, просто для случая группировки всего (без годов/месяцев/дней) можно туда вывести null - и тогда структура будет идентична.


а зачем выводить туда null? Если можно вывести "всего". Ну вывел я это через 3 поля вида
case when grouping(year(order_date)) = 1 then 0 else year(order_date) end as o_year
- кто от этого станет счастливее?

Зато вместо 3 запросов всю нужную инфу можно получить за один и не трогать базу почем зря. И не писать 3 хранимки в базе, где итак этих хранимок за сотню.

Спасибо всем, короче. Особенно за вариант
group by id, name, <year>, <month>, <day> with rollup
6 ноя 15, 19:17    [18380637]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить