将周末计数转换为星期一计数

时间:2019-05-06 20:07:00

标签: sql sql-server

我有这样的查询:

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

我需要排除星期六和星期日的日期,而是将其计数添加到下一个星期一。最好的方法是什么?我是否需要排除周六,周日和周一,然后通过加入其他查询将它们添加进来?上面的查询是简化版本,这是一个相对较大的查询,因此我需要牢记效率。

2 个答案:

答案 0 :(得分:1)

嗯,这是一种蛮力的方法:

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;

答案 1 :(得分:1)

您要声明性能,但是如果不了解整个情况,很难理解如何优化查询。

虽然我一直在努力,但我注意到Gordon Linoff的回答,但是我也会继续编写我的版本,我们都遵循相同的路径,但得出的答案略有不同。

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

虽然我无法使Gordon的查询正常工作,但我可以确认“ DATEPART(w,[date])”的性能要优于“ DATENAME(weekday,[date])”,如果在上面的查询中将其替换了,根据在Azure中填充有1万行的表,将服务器处理时间从87ms增加到181ms。