Бросок выходных учитывается в понедельник - PullRequest
1 голос
/ 06 мая 2019

У меня есть запрос, подобный следующему:

select date, count(*)
from inflow 
where date >= dateadd(year, -2, getdate())
group by date
order by date

Мне нужно исключить даты субботы и воскресенья и вместо этого добавить их значения в следующий понедельник.Каков был бы лучший способ сделать это?Нужно ли исключать субботу, воскресенье и понедельник, а затем добавить их с помощью присоединения к другому запросу?Приведенный выше запрос является упрощенной версией, это относительно большой запрос, поэтому я должен помнить об эффективности.

Ответы [ 2 ]

1 голос
/ 06 мая 2019

Вы заявляете о производительности, однако, не зная полной картины, довольно сложно понять, как оптимизировать запрос.

Пока я работал над этим, я заметил ответ Гордона Линоффа, однако я также продолжу писать свою версию, мы оба идем по одному и тому же пути, но получим ответ немного по-другому.

WITH DateData (date, datetoapply)
AS
(
    SELECT 
        [date],
        CASE DATEPART(w, [date])
            WHEN 5 THEN DATEADD(d, 2, [date])
            WHEN 6 THEN DATEADD(d, 1, [date])
            ELSE date
        END as 'datetoapply'
    FROM inflow 
    WHERE [date] >= dateadd(year, -2, getdate())
)
SELECT datetoapply, count(*)
FROM DateData
GROUP BY datetoapply
ORDER BY datetoapply

Хотя я не смог заставить запрос Гордона работать должным образом, я могу подтвердить, что «DATEPART (w, [date])» работает намного лучше, чем «DATENAME (weekday, [date])», который при замене в запросе выше увеличивает время обработки сервера с 87 мс до 181 мс на основе таблицы, заполненной 10 000 строками в Azure.

1 голос
/ 06 мая 2019

Ну, это несколько грубый подход:

select date,
       (case when datename(weekday, date) = 'Monday')
             then cnt + cnt1 + cnt2
             else cnt
        end) as cnt
from (select date, count(*) as cnt,
             lag(count(*), 1, 0) over (order by date) as prev_cnt,
             lag(count(*), 2, 0) over (order by date) as prev_cnt2
      from inflow 
      where date >= dateadd(year, -2, getdate())
      group by date
     ) d
where datename(weekday, date) not in ('Saturday', 'Sunday')
order by date;

Примечание. При этом используются англоязычные настройки, поэтому логика datename() работает.

Альтернативный метод безподзапросы;

select v.dte, count(*) as cnt
from inflow i cross apply
      (values (case when datename(weekday, i.date) = 'Saturday'
                    then dateadd(day, 2, i.date)
                    when datename(weekday, i.date) = 'Sunday'
                    then dateadd(day, 1, 9.date)
                    else i.date
               end)
      ) v.dte
where i.date >= dateadd(year, -2, getdate())
group by v.dte
order by date;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...