MySQL:是否可以使用没有表的值“填充”SELECT?

时间:2011-03-26 13:31:37

标签: mysql date select

我需要显示每年和每月的“订单”总数。但有几个月没有数据,但我想显示那个月(总值为零)。我可以用每年12条记录创造一个可靠的'月',但是有没有办法在不引入新表的情况下获得一系列月份?

类似的东西:

SELECT [all year-month combinations between january 2000 and march 2011] 
FROM DUAL AS years_months

有人知道怎么做吗?你可以使用SELECT和某种公式来“动态创建”数据吗?!

更新

自己发现: generate days from date range

这个问题中接受的答案是我正在寻找的。也许不是最简单的方法,但它可以做我想要的:根据公式填充数据选择....

在过去十年的所有月份中“创建”一张桌子:

SELECT CONCAT(MONTHNAME(datetime), ' ' , YEAR(datetime)) AS YearMonth,
       MONTH(datetime) AS Month,
       YEAR(datetime) AS Year 
FROM (
    select (curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) MONTH) as datetime
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
    LIMIT 120
) AS t
ORDER BY datetime ASC 

我必须承认,这是非常奇特的,但它有效......

我可以使用此选项将其加入我的'orders'表并获得每月的总数,即使某个月没有数据也是如此。

但使用'数字'或'日历'表可能是最好的选择,所以我将使用它。

9 个答案:

答案 0 :(得分:5)

如果可能的话,尽量避免动态生成数据。它使得非常简单的查询很复杂,但最重要的是:它使优化器混淆不已。

如果需要一系列整数,请使用整数的静态表。如果您需要一系列日期,月份或其他,请使用日历表。除非你正在处理一些非常特殊的要求,否则就可以使用静态表了。

我举例说明了如何在this answer中创建数字表和最小日历表(仅限日期)。

如果您有这些表格,则可以轻松解决您的查询。

  1. 将订单数据汇总到MONTH。
  2. 右键加入月份表(或日期表中不同的MONTH)

答案 1 :(得分:4)

你可以试试这样的事情

select * from 
    (select 2000 as year union
     select 2001 as year union
     select 2009
    ) as years, 
    (select 1 as month union 
     select 2 as month union 
     select 3 as month union 
     select 4 as month union 
     select 5 as month union 
     select 6 as month union 
     select 7 as month union 
     select 8 as month union 
     select 9 as month
     )
AS months 
WHERE year between 2001 AND 2008 OR (year=2000 and month>0) OR (year = 2009 AND month < 4) 
ORDER by year,month

答案 2 :(得分:2)

您可以在应用程序逻辑中完成查询后填写缺失的几个月。

答案 3 :(得分:1)

您绝对应该在应用程序而不是数据库层中执行此操作。只需为时间范围创建一个日期数组,并将实际数据与您预先创建的空日期合并。见this answer to similar question

答案 4 :(得分:1)

如果你正在使用PostgreSQL,你可以将date_truncgenerate_series结合起来做一些非常有趣的分组和系列生成。

例如,您可以使用它来生成去年所有日期的表格:

<div ng-repeat="x in experiences_days | orderBy: 'created_at':true | limitTo:totalDisplayed track by x._id" ng-cloak>
   <div class="container">
      <div class="row">
         <div class="col-md-4">
            {{x}}
         </div>
      </div>
   </div>
</div>

然后,您可以使用date_trunc来抓取date_trunc&#39; ed字段中的月份和分组:

SELECT current_date - s.a as date 
FROM generate_series(0,365,1) as s(a);

答案 5 :(得分:0)

创建一个包含所有12个月的表格(例如tblMonths),并使用LEFT JOIN(或RIGHT JOIN)和部分源数据。

查看the referencethis tutorial了解其工作原理。

答案 6 :(得分:0)

我会做这样的事情:

SELECT COUNT(Order.OrderID)
FROM Orders
WHERE YEAR(Order.DateOrdered) > 2000
GROUP BY MONTH(Order.DateOrdered)

这将为您提供按月分组的订单数量。 然后在您的应用程序中,只需为没有返回数据的月份分配一个ZERO

我希望这有助于

答案 7 :(得分:0)

我执行以下查询以在给定的时间间隔内生成月份。对于我的情况,它生成从2013年5月开始到现在的月份列表。

SELECT date_format(@dt:= DATE_ADD( @dt, INTERVAL 1 MONTH),'%M %Y') date_string, 
   @dt as date_full 
FROM (SELECT @dt := DATE_SUB(CAST(DATE_FORMAT('2013-05-01' ,'%Y-%m-01') AS DATE),
   INTERVAL 1 MONTH) ) vars,
   your_tables 
WHERE @dt<NOW()

值得关注的是,它应该与包含足够行的表一起提供,以提供您期望的月数。例如。如果您需要在特定年份生成所有月份,则需要一个至少包含12行的表格。

对我而言,这有点直截了当。我用我的配置表加入了它,大约有370行。因此,如果我需要,它可以在一年中产生数月,或在一年中产生数天。从月间隔变为天间隔很容易,因为我只需要将间隔从MONTH更改为DAY。

答案 8 :(得分:0)

查询静态数据 MySQL。

您可以通过此查询从带有表格的硬编码列表中选择静态数据

SELECT *
FROM (
    values row('Hamza','23'), row('Ali', '24')
) t1 (name, age);