【问题标题】:MySQL group by weekMySQL 按周分组
【发布时间】:2012-03-21 16:42:48
【问题描述】:

我有大量的交易日期时间字段可以追溯到几年前。我想在今年和去年的同一时间跨度之间进行比较分析。如何在 3 个月的范围内按周分组?

我在使用 YEARWEEK 和 WEEK 函数时遇到了问题,因为 2012 年的开始日期与 2011 年的开始日期不同。

鉴于我每天都有从 1 月 1 日到当天的日期时间记录,以及上一年具有相同日期时间的记录,我如何按周分组,以便输出与日期相加:2011 年 1 月 1 日, 01/08/2011, 01/15/2011 等,以及 01/01/2012, 01/08/2012, 01/15/2012 等?

到目前为止我的查询如下:

SELECT 
    DATE_FORMAT(A.transaction_date, '%Y-%m-%d') as date,
    ROUND(sum(A.quantity), 3) AS quantity,
    ROUND(sum(A.total_amount), 3) AS amount,
    A.product_code, 
    D.fuel_type_code, 
    D.fuel_type_name, 
    C.customer_code, 
    C.customer_name 
FROM 
    cl_transactions AS A
INNER JOIN 
    card AS B ON A.card_number=B.card_number 
INNER JOIN 
    customer AS C ON B.customer_code=C.customer_code 
INNER JOIN 
    fuel_type AS D ON A.fuel_type=D.fuel_type_code 
WHERE 
    ((A.transaction_date >= DATE_FORMAT(NOW() - INTERVAL 3 MONTH, '%Y-%m-01')) OR (A.transaction_date - INTERVAL 1 YEAR >=  DATE_FORMAT(NOW() - INTERVAL 15 MONTH, '%Y-%m-01') AND A.transaction_date <= NOW() - INTERVAL 1 YEAR))
GROUP BY 
    A.transaction_date, fuel_type_code;

我基本上想要实现以下伪查询的东西:

GROUP BY 
    STARTING FROM THE OLDEST DATE (A.transaction_date + INTERVAL 6 DAY)

【问题讨论】:

  • 如果您希望月份和日期匹配,您似乎需要 MONTH 和 DAYOFMONTH()。
  • @MarcusAdams:我也一直在研究这些日期函数,但正在努力解决如何对 7 天的组求和。

标签: mysql group-by


【解决方案1】:

我从一个内部查询开始,使用 sqlvariables 来构建今年和去年每个相应的年/月/日开始的范围(例如:分别为 2012-01-01 和 2011-01-01) .从那以后,我还预先格式化了最终输出的日期,这样你就有一个主日期基础来显示,以反映“今年”这一周的情况。

从那以后,我加入了事务表,其中事务日期在各自的本周开始和下周开始之间。由于日期/时间戳包括小时分钟,因此 2012-01-01 本身隐含为当天的上午 12:00:00(午夜)。之间将在 7 天后 12:00:00 am。并且该日期将成为下一周的开始日期。

因此,通过在去年或今年时间段之间的日期加入,它的组资格相同。因此,字段选择在去年或今年分别执行 ROUND( SUM( IF() ))。如果传入交易日期小于当年的开始日期,则它必须是上一年的记录,否则为当年的记录。因此,分别添加值本身或应用的零。

所以现在,你有 group by。它符合条件的那一周已经通过“ThisYearWeekOf”格式化列从内部查询中准备好,而不管其他计算的“YEARWEEK()”或“WEEK()”如何。日期范围为我们处理了该资格。

最后,我添加了燃料类型作为连接,并将其作为分组依据。您必须按所有非聚合列分组以获得正确的 SQL,尽管 MySQL 允许您通过获取给定组的第一个条目(如果它没有在 group by 中如此指定)来解决。

要关闭,我确实包含了客户的信息,因为您在 group by 中没有它并且似乎不适用......它只会任意抓取一个。但是,我已将其添加到分组依据,因此现在您的记录将显示每个客户级别、每个产品和燃料类型、今年和去年之间的销售额和数量。

SELECT
      JustWeekRange.ThisYearWeekOf,
      CTrans.product_code,
      FT.fuel_type_code, 
      FT.fuel_type_name, 
      C.customer_code, 
      C.customer_name,
      ROUND( SUM( IF( CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, CTrans.Quantity, 0 )), 3) as LastYrQty,
      ROUND( SUM( IF( CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, CTrans.total_amount, 0 )), 3) as LastYrAmt,
      ROUND( SUM( IF( CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, 0, CTrans.Quantity )), 3) as ThisYrQty,
      ROUND( SUM( IF( CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, 0, CTrans.total_amount )), 3) as ThisYrAmt,
   FROM 
      ( SELECT 
                 DATE_FORMAT(@ThisYearDate, '%Y-%m-%d') as ThisYearWeekOf,
                 @LastYearDate as LastYrWeekStart,
                 @ThisYearDate as ThisYrWeekStart,
                 @LastYearDate := date_add( @LastYearDate, interval 7 day ) LastYrStartOfNextWeek,
                 @ThisYearDate := date_add( @ThisYearDate, interval 7 day ) ThisYrStartOfNextWeek
            FROM 
                 (select @ThisYearDate := '2012-01-01',
                         @LastYearDate := '2011-01-01' ) sqlvars,
                 cl_transactions justForLimit
            HAVING
               ThisYrWeekStart < '2012-04-01'
            LIMIT 15 ) JustWeekRange

      JOIN cl_transactions AS CTrans
         ON    CTrans.transaction_date BETWEEN 
               JustWeekRange.LastYrWeekStart AND JustWeekRange.LastYrStartOfNextWeek
           OR  CTrans.transaction_date BETWEEN 
               JustWeekRange.ThisYrWeekStart AND JustWeekRange.ThisYrStartOfNextWeek

      JOIN fuel_type FT
         ON CTrans.fuel_type = FT.fuel_type_code

      JOIN card 
         ON CTrans.card_number = card.card_number 
         JOIN customer AS C 
            ON card.customer_code = C.customer_code 

   GROUP BY
      JustWeekRange.ThisYearWeekOf,
      CTrans.product_code,
      FT.fuel_type_code, 
      FT.fuel_type_name,
      C.customer_code, 
      C.customer_name

【讨论】:

  • 天哪,这太棒了!看起来它完全按照我的需要工作!非常感谢您花时间发布此内容并详细解释您所做的事情。非常感谢朋友!
  • 看起来像!我现在正在比较事物,它似乎正在加起来。再次感谢您的意见。
  • @btl,我能看到的唯一问题是 2012 年是 2 月 29 日......,所以下面的“开始日期”将推迟 1 天,否则应该保持同步.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2010-12-16
  • 2013-03-12
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
相关资源
最近更新 更多