按周分组

时间:2012-05-18 12:31:42

标签: sql sql-server sql-server-2005

是否有办法在SQL Server中按月分组日期?

例如

Week 2: 05/07/2012 - 05/13/2012
Week 3: 05/14/2012 - 05/20/2012

但使用Sql server语句

我试过

SELECT SOMETHING, 
     datediff(wk, convert(varchar(6), getdate(), 112) + '01', getdate()) + 1 AS TIME_
FROM STATISTICS_
GROUP BY something, TIME_
ORDER BY TIME_

但它返回月份的周数。 (意思是3)

如何获得本周的那两天?

例如,现在我们处于第三(3)周并且我想要展示 05/14/2012 - 05/20/2012

我解决了 以某种方式

SELECT DATEADD(ww, DATEDIFF(ww,0,<my_column_name>), 0)

select DATEADD(ww, DATEDIFF(ww,0,<my_column_name>), 0)+6

然后我会得到两天,我会在以后连接它们。

4 个答案:

答案 0 :(得分:3)

好吧,在这里忍受我。我们将构建一个代表本月的临时日历表,包括每月定义一周(周一至周日)之前和之后的日期。我通过很多步骤来尝试使流程清晰,但在这种情况下我可能并不擅长。

然后我们可以生成不同周的范围,您可以使用它来加入其他表格。

SET DATEFIRST 7;
SET NOCOUNT ON;

DECLARE @today SMALLDATETIME, @fd SMALLDATETIME, @rc INT;

SELECT @today = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0), -- today
    @fd = DATEADD(DAY, 1-DAY(@today), @today), -- first day of this month
    @rc = DATEPART(DAY, DATEADD(DAY, -1, DATEADD(MONTH, 1, @fd)));-- days in month

DECLARE @thismonth TABLE (
    [date]       SMALLDATETIME,
    [weekday]    TINYINT,
    [weeknumber] TINYINT 
);

;WITH n(d) AS (
    SELECT TOP (@rc+12) DATEADD(DAY, ROW_NUMBER() OVER 
    (ORDER BY [object_id]) - 7, @fd) FROM sys.all_objects
)
INSERT @thismonth([date], [weekday]) SELECT d, DATEPART(WEEKDAY, d) FROM n;

DELETE @thismonth WHERE [date] < (SELECT MIN([date]) FROM @thismonth WHERE [weekday] = 2)
                     OR [date] > (SELECT MAX([date]) FROM @thismonth WHERE [weekday] = 1);

;WITH x AS ( SELECT [date], weeknumber, rn = ((ROW_NUMBER() OVER 
   (ORDER BY [date])-1) / 7) + 1 FROM @thismonth ) UPDATE x SET weeknumber = rn;

- 现在,最后的查询给出了所有这些(我只是打破了这个以摆脱垂直滚动条):

;WITH ranges(w,s,e) AS (
    SELECT weeknumber, MIN([date]), MAX([date]) FROM @thismonth GROUP BY weeknumber
)
SELECT [week] = CONVERT(CHAR(10), r.s, 120) + ' - ' + CONVERT(CHAR(10), r.e, 120)

 --, SOMETHING , other columns from STATISTICS_?

 FROM ranges AS r

 -- LEFT OUTER JOIN dbo.STATISTICS_ AS s
 -- ON s.TIME_ >= r.s AND s.TIME_ < DATEADD(DAY, 1, r.e) 

 -- comment this out if you want all the weeks from this month: 
 WHERE w = (SELECT weeknumber FROM @thismonth WHERE [date] = @today)

 GROUP BY r.s, r.e --, SOMETHING
 ORDER BY [week];

WHERE子句的结果:

week
-----------------------
2012-05-14 - 2012-05-20

没有WHERE子句的结果:

week
-----------------------
2012-04-30 - 2012-05-06
2012-05-07 - 2012-05-13
2012-05-14 - 2012-05-20
2012-05-21 - 2012-05-27
2012-05-28 - 2012-06-03

请注意,我故意选择了YYYY-MM-DD。您应该避免像M / D / Y这样的区域格式,特别是输入和显示。无论你认为你的观众是多么有针对性,你总会有人认为05/07/2012是7月5日,而不是5月7日。 YYYY-MM-DD没有任何含糊之处。

答案 1 :(得分:2)

创建calendar table,然后您可以查询周数,特定周数和月份的第一天/最后一天等。您还可以加入查询以获取日期范围等。

答案 2 :(得分:0)

案例陈述怎么样?

case when datepart(day, mydatetime) between 1 and 7 then 1
     when datepart(day, mydatetime) between 8 and 14 then 2
     ...

你还必须包括年份&amp;月,除非你想要同一组中的所有第1周。

答案 3 :(得分:0)

您不清楚您是否要“按月份分组日期”,或者“选择某一周内的数据”

如果你的意思是“群组”,那么这个小片段应该可以让你获得“一周的一周”:

SELECT   <stuff>
FROM     CP_STATISTICS
WHERE    Month(<YOUR DATE COL>) = 5 --april
GROUP BY  Year(<YOUR DATE COL>), 
          Month(<YOUR DATE COL>),
          DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH, 0, <YOUR DATE COL>), 0)
           , <YOUR DATE COL>) +1

或者,如果您想要“4月第1周的销售额,按日期排序”,您可以做类似的事情。

DECLARE @targetDate datetime2 = '5/3/2012'
DECLARE @targetWeek int = DATEDIFF(week, DATEADD(MONTH, 
                             DATEDIFF(MONTH, 0, @targetDate), 0), @targetDate) +1


SELECT   <stuff>
FROM     CP_STATISTICS
WHERE    MONTH(@targetDate) = Month(myDateCol) AND
         YEAR(@targetDate)  = Year (myDateCol) AND 
         @targetWeek = DATEDIFF(week, DATEADD(MONTH, 
                                DATEDIFF(MONTH, 0, myDateCol), 0), myDateCol) +1
ORDER BY myDateCol

请注意,如果您使用非标准周,或者想要在跨越月份边界的数周内达到前几个月的某些日子,事情会变得更加复杂。

编辑2

从查看“现在解决”部分开始。我认为你的问题是“如何在一周内从表格中获取数据?”

您的解决方案似乎是:

DECLARE @targetDate datetime2 = '5/1/2012'
DECLARE @startDate  datetime2 = DATEADD(ww, DATEDIFF(ww,0,targetDate), 0)
DECLARE @endDate    datetime2 = DATEADD(ww, DATEDIFF(ww,0,@now), 0)+6

SELECT  <stuff>
FROM    STATISTICS_
WHERE   dateStamp >= @startDate AND dateStamp <= @endDate

请注意,如果日期为5/1,此解决方案将导致开始日期为“4/30/2012”。我指出这一点是因为你的解决方案跨越了月界限。这可能是也可能不是。