我需要显示每年和每月的“订单”总数。但有几个月没有数据,但我想显示那个月(总值为零)。我可以用每年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'表并获得每月的总数,即使某个月没有数据也是如此。
但使用'数字'或'日历'表可能是最好的选择,所以我将使用它。
答案 0 :(得分:5)
如果可能的话,尽量避免动态生成数据。它使得非常简单的查询很复杂,但最重要的是:它使优化器混淆不已。
如果需要一系列整数,请使用整数的静态表。如果您需要一系列日期,月份或其他,请使用日历表。除非你正在处理一些非常特殊的要求,否则就可以使用静态表了。
我举例说明了如何在this answer中创建数字表和最小日历表(仅限日期)。
如果您有这些表格,则可以轻松解决您的查询。
答案 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_trunc和generate_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 reference和this 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)
您可以通过此查询从带有表格的硬编码列表中选择静态数据
SELECT *
FROM (
values row('Hamza','23'), row('Ali', '24')
) t1 (name, age);