Pull to refresh

Comments 15

средняя по средней- какая прелесть))
Особенно приятно удивление бизнеса из серии: "а шо это?" когда он (бизнес) начинает менять очередность измерений в заголовках строк сводной и видит изменение этой "средней".

У них большое совещание было, когда я это сделал. Не знаю, может специально решили мне накинуть задачку, думали не справлюсь. А когда я сделал как они хотели, то уже им пришлось думать, а не мне им объяснять.:)

Последнее преобразование у меня не работает. Формирую тестовую таблицу:
SELECT * INTO Test FROM (Values (1,'2017-01-01'),(2,'2017-01-02'),(3,'2017-01-03'),(3,'2017-01-04'),(3,'2017-01-05'),(4,'2017-01-06'),(5,'2017-01-07'),(6,'2017-01-05')) AS t(Volume,Date)

После работы преобразования получаю:
data VT_BEG VT_END
3 2017-01-03 2017-01-05

Я поправил, спасибо за подсказку. Пример переделывал из рабочего пакета, недоглядел. Вообщем — "Поспешишь людей насмешишь!".

Можете посмотреть execution plan на своем сервере. Итоговый запрос больше для примера, что идея, которую я описал работает. Это ответ на вопрос от AlexeyTopunov, случайно не в ту ветку попал.

А итоговый запрос не слишком сложный получился? Можно посмотреть execution plan?

Слишком сложный запрос, все пишется в пару строк и без CTE:


SELECT volume,  MIN(date) AS VT_BEG,  MAX(date) AS VT_END
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY date) - ROW_NUMBER() OVER (PARTITION BY volume ORDER BY date) as grp FROM #test) t
GROUP BY volume,grp ORDER BY VT_BEG

Не хочу спорить. У каждого свое видение, но я писал немного о другом. Пример ниже.


SELECT * INTO Test FROM (VALUES (1,'2017-01-01'),(2,'2017-01-02'),(3,'2017-01-03'),(3,'2017-01-04'),(3,'2017-01-05'),(4,'2017-01-06'),(1,'2017-01-10'),(1,'2017-01-11'),(1,'2017-01-15')) AS t(Volume, DATE)

Просто Ваша статья о том как Вы "изобретали велосипед", то что Вы пытаетесь сделать это классическая проблема "Gaps and Islands", по ней можно найти кучу статей в сети и у нее есть классическое решение.

Создаю таблицу запросом:


SELECT * INTO Test FROM (VALUES (1,'2017-01-01'),(2,'2017-01-02'),(3,'2017-01-03'),(3,'2017-01-04'),(3,'2017-01-05'),(4,'2017-01-06'),(1,'2017-01-10'),(1,'2017-01-11'),(1,'2017-01-15')) AS t(Volume, DATE)

Получается табличка:
1 2017-01-01
2 2017-01-02
3 2017-01-03
3 2017-01-04
3 2017-01-05
4 2017-01-06
1 2017-01-10
1 2017-01-11
1 2017-01-15
Делаю Ваш запрос:


SELECT volume,  MIN(date) AS VT_BEG,  MAX(date) AS VT_END
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY date) - ROW_NUMBER() OVER (PARTITION BY volume ORDER BY date) as grp FROM #test) t
GROUP BY volume,grp ORDER BY VT_BEG

Получаю для Volume = 1 два периода:
1 2017-01-01 2017-01-01
1 2017-01-10 2017-01-15
Хотя периода было 3:
1 2017-01-01 2017-01-01
1 2017-01-10 2017-01-11
1 2017-01-15 2017-01-15


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

SELECT volume, convert(datetime,date) as date INTO #Test FROM (VALUES (1,'2017-01-01'),(2,'2017-01-02'),(3,'2017-01-03'),(3,'2017-01-04'),(3,'2017-01-05'),(4,'2017-01-06'),(1,'2017-01-10'),(1,'2017-01-11'),(1,'2017-01-15')) AS t(Volume, DATE)

;with cte as (
select volume, date, 
    isnull(LEAD(date) over (ORDER BY date), date+10) as nd,  
    isnull(LEAD(volume) over (ORDER BY date), volume+1) as nv, 
    isnull(LAG(date) over (order by date),date-10) as pd,
    isnull(LAG(volume) over (ORDER BY date), volume-1) as pv 
from #test
)
select s.volume, s.date as vt_beg, e.date  as vt_end
from (select row_number() over (order by date) as rn, volume, date from cte where date>pd+1 or volume <> pv) s
join (select row_number() over (order by date) as rn, date from cte where date<nd-1 or volume <> nv) e on s.rn = e.rn

Вот так подойдет? :)… Кстати если у Вас есть большой объем реальных данных интересно какой запрос и во сколько раз работает быстрей потому что, на маленьком объеме поведение практически идентичное, а план сервер категорически отказывается.

Ну как так????


SELECT volume, convert(datetime,date) as date INTO Test FROM (VALUES (1,'2017-01-01'),(2,'2017-01-02'),(3,'2017-01-03'),(3,'2017-01-04'),(3,'2017-01-05'),(4,'2017-01-06'),(1,'2017-01-10'),(1,'2017-01-11'),(1,'2017-01-15'), (null,'2017-01-05'), (5,'2017-01-05')) AS t(Volume, DATE)


Тогда такой набор не будет в Вашем случае работать. Как бы может не надо такое сюда писать? Я ведь помочь хочу людям, а не чужие запросы проверять.

Так это найти все начала периодов, сравнив данные с предыдущим, и все концы периодов сделав то же самое с последующими потом объединить попарно начала и концы, не выделяя отдельно однодневные и прочие периоды. Насчет NULL значений в поле Value вы меняете постановку на ходу, понимаю что ваш заказчик всегда делает так же, но может в рамках статьи этого делать не нужно? Если вы думаете что вы сделали великое открытие вы ошибаетесь и в данном случае скорее вопрос реализации и ваша реализация просто уродлива. Я пытался написать нормальный запрос с нормальной идеей, но если автору самому не интересна тема обсуждения, то я темболее не вижу в нем смысла. Автор любит свой велосипед и агрессивен ко всем кто отказывается его "полюбить" :).

Причем тут постановка? Мой запрос ничего не теряет и работает тем не менее с таким набором. Если кто-то будет пользоваться этим запросом, то получив Null у него все как работало так и будет работать. И там не только NULL, как насчет (5,'2017-01-05')? Я не ставил постановку, я просто привел пример. Запрос должен работать с любыми наборами, как минимум не терять данные и я постарался сделать так чтобы он работал.

Я пытался сделать запрос как можно более понятным и выделить в нем ключевую идею. Глубоким тюнингом я не занимался.

Sign up to leave a comment.

Articles