为什么 MySQL SUM IF 在 2021 年停止工作

时间:2021-02-04 02:01:03

标签: mysql

此代码在 2020 年工作后于 2021 年停止工作:

SELECT name, SUM(CASE WHEN YEARWEEK(prod_date) = YEARWEEK(now()- INTERVAL 1 WEEK) THEN gas_prod ELSE NULL END) AS LastWeek FROM daily_prod GROUP BY name

代码现在计算出的数字大于上周的数字。为什么新年会导致此代码以不同的方式工作?

1 个答案:

答案 0 :(得分:0)

首先,在这里使用 sum( case/when ) 是一个糟糕的选择。您的查询与您的 ENTIRE daily_prod 表 EVERY RECORD 背道而驰,但仅在给定的 yeardate() 期间内基于当前日期进行求和。与其这样做,不如构建一个 WHERE 子句来获取您关心的记录。 YearWeek() 函数基于周日到周六的周计划。因此,例如本周是从 1 月 31 日凌晨 12:00(午夜)到但不包括 2 月 7 日午夜 12:00。这包括截至 2 月 6 日晚上 11:59:59 的所有内容。

因此,通过执行嵌入式 MySQL 变量,您可以构建为“来自”表别名,正如我将展示的那样。首先,让我们获取当前 NOW() 的任何内容,其中包括小时/分钟/秒,并将其剥离到日期部分。例如:2021-02-04 @ 01:42am 截断为仅 2021-02-04 12:00am

select cast( now() as date )

从那以后,我们需要转到一周的第一天,表示为星期日。为此,我们使用星期几并减去 1,因此它是一个从零开始的值,其中星期日 = 0,星期六 = 6。所以星期四,通常返回 5,减去 1 = 4。二月 4 - 4 天 = 一月 31这是本周的第一天。

select date_sub( [result of sql above], interval dayofweek( [result of sql above] ) -1 day )

现在,由于您需要整周的数据,在这种情况下,您的数据将是从 1 月 31 日上午 12:00 到 2 月 6 日(星期六)晚上 11:59:59。因此,从上述一周的开始,再加上 1 周,将您带到 2 月 7 日。

select  date_add( [result of 2nd query], interval 1 week )

是的,这是有意为之,因为现在在您的最终查询中,您可以查询 LESS THAN 2 月 7 日。

因此,通过在数据源上使用 where,您只能获取这些记录,并且,如果您的表在交易日期有索引,则可以针对查询进行优化。要使用内联变量,我们可以将它们的结果用作查询的一部分,例如:

SELECT 
      dp.name, 
      SUM( dp.gas_prod ) CurrwntWeekGas 
   FROM 
      daily_prod dp,
      ( select
               -- first, variable @nd = Now as a date only
               @nd := cast( now() as date ),
               -- from the @nd, subtract 0-based day of week
               -- example: Thursday is 5th day of week -1 = 4 days to subtract
               @fow := date_sub( @nd, interval dayofweek( @nd ) -1 day ),
               -- finally from the first of the week, add 1 week to the END point for the query
               @nextWeek := date_add( @fow, interval 1 week )
      ) sqlvars
   where
         -- only grab records greater or equal to the first day of the week
          dp.prod_date >= @fow
      -- and ALSO LESS then the the beginning of NEXT week
      AND dp.prod_date < @nextWeek
   GROUP BY 
      dp.name

因此,在处理 from 子句别名“sqlvars”时,它会创建 3 个“@”变量来定义一周的开始和 NEXT 周的开始值。然后可以将这些应用于 where 子句并仅限制您需要的记录,而不是整个表。

如果你真的想要你所在周的前一周的结果...... 例如:从 1 月 24 日到 1 月 30 日的总数,因为本周尚未完成,那么只需将你的 dayofweek() -1 更改为dayofweek() -8 获取整个前一周,而不是您现在所处的当前周。