【问题标题】:generate_series() equivalent in MySQLMySQL 中的 generate_series() 等价物
【发布时间】:2011-10-15 18:39:13
【问题描述】:

我需要查询并加入一年中的所有日子,但在我的数据库中没有日历表。
谷歌搜索后,我在 PostgreSQL 中找到了generate_series()。 MySQL有类似的东西吗?

我的实际表是这样的:

date     qty
1-1-11    3
1-1-11    4
4-1-11    2
6-1-11    5

但我的查询必须返回:

1-1-11    7
2-1-11    0
3-1-11    0
4-1-11    2
and so on ..

【问题讨论】:

  • 为什么不能在你的应用逻辑层做这个?
  • 这不是应用逻辑中的“正确”解决方案。通过 sql 做的更好,真的更好(如果可能的话)。如果它不可能......好吧,我会在我的应用程序逻辑中做......
  • @stighly:嗯,你可以在 MySQL 上解决一半的问题。也就是说,您可以GROUP BY dateSUM(qty) qty,但我不记得有什么解决方案可以为缺失的序列添加行。最好在应用逻辑中进行,如果日期有 qty 值,则显示,否则显示 0。
  • 实际上,我正在解决它生成一个完整的日历表......从 1-1-2010(例如)到 31-12-2020。它有效..但它不是很优雅......

标签: mysql sql generate-series


【解决方案1】:

以防万一有人正在寻找 generate_series() 来生成一系列日期或整数作为 MySQL 中的临时表。

使用 MySQL8(MySQL 版本 8.0.27)你可以做这样的事情来模拟:

WITH RECURSIVE nrows(date) AS (
SELECT MAKEDATE(2021,333) UNION ALL 
SELECT DATE_ADD(date,INTERVAL 1 day) FROM nrows WHERE  date<=CURRENT_DATE
)
SELECT date FROM nrows;

结果:

2021-11-29
2021-11-30
2021-12-01
2021-12-02
2021-12-03
2021-12-04
2021-12-05
2021-12-06

【讨论】:

    【解决方案2】:

    来自@Karolis 的增强版解决方案,确保它适用于任何年份(包括闰年):

    select date from (
        select
            date_format(
            adddate('2011-1-1', @num:=@num+1),
            '%Y-%m-%d'
        ) date
        from
            any_table,
        (select @num:=-1) num
        limit
            366
    ) as dt
    where year(date)=2011
    

    【讨论】:

      【解决方案3】:

      我一直在寻找这个解决方案,但没有“硬编码”日期,我想出了这个在当年有效的解决方案(来自answers)。 请注意

      where year(date)=2011
      

      不需要,因为选择已经过滤了日期。同样这样,使用哪个表(至少在该表至少有 366 行之前所述)并不重要,因为日期是在运行时“计算”的。

       select date from (
          select
              date_format(
              adddate(MAKEDATE(year(now()),1), @num:=@num+1),
              '%Y-%m-%d'
          ) date
          from
              your_table,
          (select @num:=-1) num
          limit
              366 ) as dt
      

      【讨论】:

        【解决方案4】:

        这就是我的做法。它创建从 2011-01-012011-12-31 的日期范围:

        select 
            date_format(
                adddate('2011-1-1', @num:=@num+1), 
                '%Y-%m-%d'
            ) date
        from 
            any_table,    
            (select @num:=-1) num
        limit 
            365
        
        -- use limit 366 for leap years if you're putting this in production
        

        唯一的要求是 any_table 中的行数应大于或等于所需范围的大小(在本例中>= 365 行)。您很可能会将其用作整个查询的子查询,因此在您的情况下,any_table 可以是您在该查询中使用的表之一。

        【讨论】:

        • 非常老套,但就像一个魅力。我完全在使用它。比我看到的其他方法好得多。
        • 闰年不会中断吗?
        • @Milimetric 否。它只连续输出 365 天,但闰年可能需要limit 366
        • @Milimetric 将您的观察结果显示为 cmets,而不是编辑答案。
        • 恕我直言,答案是错误的,应该进行编辑。这是一个解决方案的 wiki。复制和粘贴该代码的人可能没有想到我提到的特殊情况并被它烧毁。因此,应该编辑答案。我不想卷入一场回归战争,但你应该把我的评论加回来。
        猜你喜欢
        • 2023-03-05
        • 1970-01-01
        • 2011-02-13
        • 2010-09-20
        • 1970-01-01
        • 2021-03-06
        • 2012-05-04
        • 2023-04-05
        • 2010-12-06
        相关资源
        最近更新 更多