【问题标题】:break down by weeks in SQL Server在 SQL Server 中按周分解
【发布时间】:2010-11-16 16:23:12
【问题描述】:

鉴于此查询:

DECLARE 
@FROM_DT DATETIME, 
@TO_DT     DATETIME

BEGIN
SET @FROM_DT = '10/01/2009' 
SET @TO_DT   = DATEADD(DAY,7,@FROM_DT)
--WHILE (@FROM_DT <= '10/01/2010')
WHILE (@TO_DT < '10/01/2010')


BEGIN
SELECT 
CONVERT(CHAR(10),@FROM_DT,101)               AS FROM_DT, 
CONVERT(CHAR(10),DATEADD(DAY,-1,@TO_DT),101) AS TO_DT,
COUNTRY                                      AS CITZ,
COUNT(SUBJECT_KEY)                           AS PEOPLE
FROM MYTALE
WHERE DATE_DT >=@FROM_DT
AND DATE_DT   <@TO_DT
GROUP BY COUNTRY

SET @FROM_DT = DATEADD(DAY,7,@FROM_DT)
SET @TO_DT     = DATEADD(DAY, 7,@TO_DT)
END
END

这是我的结果:

FROM_DT TO_DT       COUNTRY PEOPLE
10/01/2009  10/07/2009  A       2
10/01/2009  10/07/2009  B       1

FROM_DT TO_DT       COUNTRY PEOPLE
10/08/2009  10/14/2009  A       1
10/08/2009  10/14/2009  C       2

 ---to
FROM_DT TO_DT       COUNTRY PEOPLE
09/23/2010  09/29/2010  A       1
09/23/2010  09/29/2010  B       3

FROM_DT TO_DT       COUNTRY PEOPLE
09/30/2010  10/06/2010  C       13
09/30/2010  10/06/2010  D       1

问题:

SQL 中有没有一种方法可以编写如下输出? (我需要整合数据。我可以复制和粘贴它们,但这是 52 周的数据。不是一种有效的方法)请帮忙。我使用 SQL Server 2005 & 2008 版本。

FROM_DT TO_DT       COUNTRY PEOPLE
10/01/2009  10/07/2009  A       2
10/01/2009  10/07/2009  B       1
10/08/2009  10/14/2009  A       1
10/08/2009  10/14/2009  C       2
09/23/2010  09/29/2010  A       1
09/23/2010  09/29/2010  B       3
09/30/2010  10/06/2010  C       13
----

从上面的查询中,我将 WHILE (@FROM_DT

【问题讨论】:

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


    【解决方案1】:

    好吧,SQL Server 有一个名为 DATEPART 的函数,它还可以为您提供日期的 WEEK 部分 - 类似于:

    SELECT 
      DATEPART(WEEK, DATE_DT)
      Country AS CITZ,
      COUNT(Subject_Key) AS PEOPLE
    FROM dbo.MyTable
    GROUP BY 
       Country, DATEPART(WEEK, DATE_DT)
    

    这会为您提供数字周数(但还不是 from_date 和 to_date)。

    或者您可以不理会基本查询,但将结果存储到临时表中:

    CREATE TABLE dbo.tmp_Results(FromDT CHAR(10), ToDT CHAR(10), 
                                 Country VARCHAR(100), Count INT)
    

    然后在每次运行时将结果插入到该表中:

    INSERT INTO dbo.tmp_Results(FromDT, ToDT, Country, Count)
      SELECT 
         CONVERT(CHAR(10),@FROM_DT,101)               AS FROM_DT, 
         CONVERT(CHAR(10),DATEADD(DAY,-1,@TO_DT),101) AS TO_DT,
         COUNTRY                                      AS CITZ,
         COUNT(SUBJECT_KEY)                           AS PEOPLE
      FROM MYTALE
      WHERE DATE_DT >=@FROM_DT
      AND DATE_DT   <@TO_DT
      GROUP BY COUNTRY
    

    然后最后从那个临时表中选择:

    SELECT * FROM dbo.tmp_Results
    

    【讨论】:

      【解决方案2】:

      递归 CTE 助你一臂之力!不再需要临时表,因为您可以动态生成集合,并且可以在任何日期而不是星期一开始一周。

      (危险:写在记事本中。可能存在小错误/错别字。但想法正确)

      WITH weeks (start, end) AS (
        select
          @from_dt as start
          dateadd(day, 7, @from_dt) as end
        UNION
        select
          dateadd(day, start, 7)
          dateadd(day, end, 7)
        from
          weeks
        where
          start < @last_dt
      )
      select
        w.start,
        w.end,
        c.country,
        count(c.subject_key)
      from
        my_table c
        join weeks on c.date_dt >= start and c.date_dt < end
      group by
        start, end, country
      

      【讨论】:

        【解决方案3】:

        您可以使用带有联合子句的动态查询,但我要做的是创建一个临时表并将结果插入其中。然后你可以从那里选择数据并删除临时表。

        您的另一个选择是创建一个表格,保留您几周的从开始日期,然后加入该表格。这实际上是一种首选方式,但您需要使该表与您需要的所有日期保持同步。

        【讨论】:

          【解决方案4】:

          数据仓库的一种方法是创建一个“周”表,其中包含所有可能的周,以及它们的开始和结束日期:

          Week    StartDate   EndDate
          1       10/01/2009  10/07/2009
          2       10/08/2009  10/14/2009
          3       10/15/2009  10/21/2009
          ...
          

          ...然后就加入其中。您可以预先填写“周”表一次——如果需要,您可以将其填写到 3000 年——然后它就可以在您的数据库中进行如下查询:

          SELECT 
            StartDate, EndDate, COUNTRY, COUNT(SUBJECT_KEY) AS People
          FROM 
            MYTALE INNER JOIN Weeks ON DATE_DT BETWEEN StartDate AND EndDate
          GROUP BY 
            StartDate, EndDate, Country 
          

          当您需要对一系列日期进行数据分析时,这通常会简化复杂的查询(并且您可以预先构建类似的“天”或“月”表)。假设您已编制索引,它还可以更快适当的表格。这些表是星型数据仓库用语中的“时间维度”。

          【讨论】:

            【解决方案5】:

            试试:

            DECLARE 
            @FROM_DT DATETIME, 
            @TO_DT     DATETIME
            
            BEGIN
            SET @FROM_DT = '10/01/2009' 
            SET @TO_DT   = DATEADD(DAY,7*53,@FROM_DT)
            
            SELECT 
            CONVERT(CHAR(10),DATEADD(DAY,7*(WEEKNO),@FROM_DT),101)   AS FROM_DT, 
            CONVERT(CHAR(10),DATEADD(DAY,7*(WEEKNO)+6,@FROM_DT),101) AS TO_DT,
            COUNTRY                                                  AS CITZ,
            COUNT(SUBJECT_KEY)                                       AS PEOPLE
            (SELECT M.*, TRUNC(DATEDIFF(DAY,@FROM_DT,DATE_DT)/7) WEEKNO
             FROM MYTALE M
             WHERE DATE_DT >=@FROM_DT
             AND DATE_DT   <@TO_DT) SQ
            GROUP BY COUNTRY, WEEKNO
            
            END
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-03-06
              相关资源
              最近更新 更多