对于下表:
CREATE TABLE products
(
date DATE,
productname VARCHAR(80),
quantity INT(5)
);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-12-16','toy',5);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-12-18','santa',8);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-12-23','tree',15);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-10-01','toy',10);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-10-04','santa',20);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-10-09','tree',30);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-10-01','toy',40);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-10-04','santa',30);
INSERT INTO `products`(`date`, `productname`, `quantity`) VALUES ('2016-10-09','tree',20)
我有以下数据透视查询:
SELECT DATE_FORMAT(`date`, '%Y-%m') As Date,
IFNULL(Sum(Case when `productname` = 'santa' then `quantity` end),0) As santa,
IFNULL(Sum(Case when `productname` = 'toy' then `quantity` end),0) As toy,
IFNULL(Sum(Case when `productname` = 'tree' then `quantity` end),0) As tree
FROM `products`
WHERE `Date` BETWEEN '2016-10' and '2016-12'
GROUP BY DATE_FORMAT(`date`, '%Y-%m');
结果如何:
+---------+-------+------+------+
| Date | santa | toy | tree |
+---------+-------+------+------+
| 2016-10 | 50 | 50 | 50 |
+---------+-------+------+------+
| 2016-12 | 8 | 5 | 15 |
+---------+-------+------+------+
哪个效果很好,但即使当月没有数据,我也希望包含给定间隔的所有月份。因此,在上面的示例中,我希望有这样的结果:
+---------+-------+------+------+
| Date | santa | toy | tree |
+---------+-------+------+------+
| 2016-10 | 50 | 50 | 50 |
+---------+-------+------+------+
| 2016-11 | 0 | 0 | 0 |
+---------+-------+------+------+
| 2016-12 | 8 | 5 | 15 |
+---------+-------+------+------+
是否可以使用SQL?
答案 0 :(得分:1)
规范方法是从月份列表开始并使用left join
:
SELECT DATE_FORMAT(m.month_start, '%Y-%m') as yyyymm,
Sum(Case when productname = 'santa' then quantity else 0 end) As santa,
Sum(Case when productname = 'toy' then quantity else 0 end) As toy,
Sum(Case when productname = 'tree' then quantity else 0 end) As tree
FROM (SELECT DATE('2016-10-01') as month_start UNION ALL
SELECT DATE('2016-11-01') as month_start UNION ALL
SELECT DATE('2016-12-01') as month_start
) m LEFT JOIN
products p
ON p.Date >= m.month_start AND
p.Date < m.month_start + interval 1 month
GROUP BY DATE_FORMAT(m.month_start, '%Y-%m')
ORDER BY yyyymm;
注意:
ORDER BY
在MySQL中不是必需的,但保证GROUP BY
进行排序是不推荐的行为。SUM()
条款,则NULL
无法返回ELSE
。答案 1 :(得分:0)
您可以使用交叉连接技巧生成日期范围,然后将表格与其连接并聚合以获得所需的结果。
select c.ym,
coalesce(santa,0) santa,
coalesce(toy,0) toy,
coalesce(tree,0) tree
from (
SELECT DATE_FORMAT(`date`, '%Y-%m') As ym,
IFNULL(Sum(Case when `productname` = 'santa' then `quantity` end),0) As santa,
IFNULL(Sum(Case when `productname` = 'toy' then `quantity` end),0) As toy,
IFNULL(Sum(Case when `productname` = 'tree' then `quantity` end),0) As tree
FROM `products`
GROUP BY DATE_FORMAT(`date`, '%Y-%m')
) t right join (select ym
from (
select date_format(str_to_date('2016-10-01','%Y-%m-%d') + INTERVAL (a.a + (10 * b.a)) MONTH,'%Y-%m') as ym
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
) a
where ym between '2016-10' and '2016-12'
) c on t.ym = c.ym;
产地:
Date santa toy tree
1 2016-10 50 50 50
2 2016-11 0 0 0
3 2016-12 8 5 15