每周计数拆分为多行

时间:2017-08-24 13:17:19

标签: sql sql-server

我想从表中获取一周的项目数,我使用了以下查询:

SELECT 
    count(*) As Total 
from MyTable 
WHERE convert(date,DateCreated)>='08/17/2015'
AND convert(date,DateCreated)<='08/23/2015'

我得到的结果是(这是正确的):

    Total
    1149    

现在我尝试重写查询以使其在一段时间内每周返回结果,并且我注意到计数未正确显示。 作为示例,我在同一时间段内使用了以下查询:

SELECT 
    count(*) AS Total,
    DATEPART(wk, DateCreated) AS WeekNumber,
    CAST(dateadd(ww, datediff(ww, 0, DateCreated), 0) AS date) as WeekStartDate,
    CAST(dateadd(ww, datediff(ww, 0, DateCreated), 6) AS date) as WeekEndDate
FROM MyTable 
WHERE convert(date,DateCreated) >= '08/17/2015'
and convert(date,DateCreated) <= '08/23/2015'
GROUP BY DATEPART(wk, DateCreated), CAST(dateadd(ww, datediff(ww, 0, DateCreated), 0) AS date), CAST(dateadd(ww, datediff(ww, 0, DateCreated), 6) AS date) 
ORDER BY DATEPART(wk, DateCreated)

SUM行正在返回正确的计数,但由于我的日期选择(从'08/17/2015''08/23/2015')仅代表一周,因此预计它将只作为一行,但结果如下所示为2周

    Total   WeekNumber  WeekStartDate   WeekEndDate
    1078    34           2015-08-17     2015-08-23
    71      35           2015-08-24     2015-08-30

此行为的任何已知原因。是因为我使用的周计算逻辑吗?或者其他一些已知问题。

3 个答案:

答案 0 :(得分:3)

您正在按DATEPART(wk...分组

这使用您服务器的DATEFIRST设置。它与计算WeekStartDate和WeekEndDate的方式不同,因此它将提供与您预期不同的WeekNumber,除非您的DATEFIRST值设置为重合。

2015年,8月17日是星期一,8月23日是星期天。你有DATEFIRST Set to Monday吗?默认为星期日。

参见&#34; Week和DatePart参数&#34; MS Documentation

的部分

编辑:This answer根据您当前的DATEFIRST值提供一些详细解释和提示,以获取一周的第一天。

答案 1 :(得分:1)

由于Tab最终没有提供可行的解决方案,因此这里有一个:

set datefirst 1;

select 
    count(*) as Total
  , datepart(wk, DateCreated) as WeekNumber
  , convert(date,dateadd(week,datediff(day,0,DateCreated )/7,0)) as WeekStartDate
  , convert(date,dateadd(week,datediff(day,0,DateCreated )/7,6)) as WeekEndDate
from MyTable 
where convert(date,DateCreated) >= '20150817' --'08/17/2015'
  and convert(date,DateCreated) <= '20150823' --'08/23/2015'
group by 
    datepart(wk, DateCreated)
  , convert(date,dateadd(week,datediff(day,0,DateCreated )/7,0)) 
  , convert(date,dateadd(week,datediff(day,0,DateCreated )/7,6)) 
order by datepart(wk, DateCreated)

简单的日历示例:

declare @FromDate date = '20150817';
declare @ThruDate date = '20150831';
;with cal as (
  select top (1+datediff(day, @FromDate, @ThruDate))
      DateValue = convert(date,dateadd(day,row_number() over (order by (select 1))-1,@FromDate))
  from [master]..spt_values v
  order by DateValue
)
select 
    [Date]     = convert(char(10),DateValue,120)
  , weekday    = datename(WeekDay,DateValue)
  , WeekMonday = convert(date,dateadd(week,datediff(day,0,datevalue )/7,0))
  , WeekSunday = convert(date,dateadd(week,datediff(day,0,datevalue )/7,6))
from cal

rextester演示:http://rextester.com/TYJ50600

返回:

+------------+-----------+------------+------------+
|    Date    |  weekday  | WeekMonday | WeekSunday |
+------------+-----------+------------+------------+
| 2015-08-17 | Monday    | 2015-08-17 | 2015-08-23 |
| 2015-08-18 | Tuesday   | 2015-08-17 | 2015-08-23 |
| 2015-08-19 | Wednesday | 2015-08-17 | 2015-08-23 |
| 2015-08-20 | Thursday  | 2015-08-17 | 2015-08-23 |
| 2015-08-21 | Friday    | 2015-08-17 | 2015-08-23 |
| 2015-08-22 | Saturday  | 2015-08-17 | 2015-08-23 |
| 2015-08-23 | Sunday    | 2015-08-17 | 2015-08-23 |
| 2015-08-24 | Monday    | 2015-08-24 | 2015-08-30 |
| 2015-08-25 | Tuesday   | 2015-08-24 | 2015-08-30 |
| 2015-08-26 | Wednesday | 2015-08-24 | 2015-08-30 |
| 2015-08-27 | Thursday  | 2015-08-24 | 2015-08-30 |
| 2015-08-28 | Friday    | 2015-08-24 | 2015-08-30 |
| 2015-08-29 | Saturday  | 2015-08-24 | 2015-08-30 |
| 2015-08-30 | Sunday    | 2015-08-24 | 2015-08-30 |
| 2015-08-31 | Monday    | 2015-08-31 | 2015-09-06 |
+------------+-----------+------------+------------+

答案 2 :(得分:0)

您应该使用iso_week作为日期部分,请看:

 select 
     datepart(wk,'20150817'),  
     datepart(wk,'20150823'),
     datepart(iso_week,'20150817'),  
     datepart(iso_week,'20150823')