我正在计算每个月有多少结果。
这是我的疑问:
SELECT
COUNT(*) as nb,
CONCAT(MONTH(t.date),0x3a,YEAR(t.date)) as period
FROM table1 t
WHERE t.criteria = 'value'
GROUP BY MONTH(t.date)
ORDER BY YEAR(t.date)
我的结果:
nb period
---------------
7 6:2009
46 8:2009
2 10:2009
1 11:2009
14 1:2009
9 9:2010
161 7:2010
5 2:2010
88 3:2010
28 4:2010
4 5:2011
2 12:2011
问题是,我确信我的结果是5:2011& 12:2011,以及每个其他时期 自2009年......:/
这是我的请求或mysql配置的问题吗?
很多
答案 0 :(得分:3)
您必须按年份和月份进行分组。否则,您的2012年4月行也将与2011年4月(以及2010年4月......)行分组。
SELECT
COUNT(*) AS nb,
CONCAT(MONTH(t.date), ':', YEAR(t.date)) AS period
FROM table1 AS t
WHERE t.criteria = 'value'
GROUP BY YEAR(t.date)
, MONTH(t.date) ;
(您使用0x3a
而不是':'
的原因是否有原因?)
你也可以使用其他一些DATE and TIME functions的MySQL,这样每行调用的函数就更少了,可能是一个更有效的查询:
SELECT
COUNT(*) AS nb,
DATE_FORMAT(t.date, '%m:%Y') AS period
FROM table1 AS t
WHERE t.criteria = 'value'
GROUP BY EXTRACT( YEAR_MONTH FROM t.date) ;
对于多个查询,在数据库中使用永久日历表(包含所有日期或所有年 - 月)或甚至几个日历表都很有用。例如:
CREATE TABLE CalendarYear
( Year SMALLINT UNSIGNED NOT NULL
, PRIMARY KEY (Year)
) ENGINE = InnoDB ;
INSERT INTO CalendarYear
(Year)
VALUES
(1900), (1901), ..., (2099) ;
CREATE TABLE CalendarMonth
( Month TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (Month)
) ENGINE = InnoDB ;
INSERT INTO CalendarMonth
(Month)
VALUES
(1), (2), ..., (12) ;
这些也可以帮助我们制作出我们需要的那个:
CREATE TABLE CalendarYearMonth
( Year SMALLINT UNSIGNED NOT NULL
, Month TINYINT UNSIGNED NOT NULL
, FirstDay DATE NOT NULL
, NextMonth_FirstDay DATE NOT NULL
, PRIMARY KEY (Year, Month)
) ENGINE = InnoDB ;
INSERT INTO CalendarYearMonth
(Year, Month, FirstDay, NextMonth_FirstDay)
SELECT
y.Year
, m.Month
, MAKEDATE(y.Year, 1) + INTERVAL (m.Month-1) MONTH
, MAKEDATE(y.Year, 1) + INTERVAL (m.Month) MONTH
FROM
CalendarYear AS y
CROSS JOIN
CalendarMonth AS m ;
然后,您可以使用日历表来编写更复杂的查询,例如您想要的变体(缺少月份),并且可能更有效。测试 SQL-Fiddle :
SELECT
COUNT(t.date) AS nb,
CONCAT(cal.Month, ':', cal.Year) AS period
FROM
CalendarYearMonth AS cal
JOIN
( SELECT
YEAR(MIN(date)) AS min_year
, MONTH(MIN(date)) AS min_month
, YEAR(MAX(date)) AS max_year
, MONTH(MAX(date)) AS max_month
FROM table1
WHERE criteria = 'value'
) AS mm
ON (cal.Year, cal.Month) >= (mm.min_year, mm.min_month)
AND (cal.Year, cal.Month) <= (mm.max_year, mm.max_month)
LEFT JOIN
table1 AS t
ON t.criteria = 'value'
AND t.date >= cal.FirstDay
AND t.date < cal.NextMonth_FirstDay
GROUP BY
cal.Year, cal.Month ;
答案 1 :(得分:2)
您还必须GROUP BY
年份:
GROUP BY MONTH(t.date), YEAR(t.date)
您的原始查询在任何聚合函数之外的YEAR(t.date)
子句中使用SELECT
而不进行分组 - 因此,您可以获得12个组(每个可能的月份一个)组(可能包含多年的日期)a&#34;随机&#34; mySql选择year作为选择。严格地说,这是没有意义的,并且永远不应该允许执行查询。但MySql ... 叹息。