我有一个存储产品版本(product_versions
)的表。这些产品版本可以有一组状态(active
, draft
, archived
),我需要每天(历史上)获取这些状态的聚合结果集,以便生成图表。
虽然我知道我可以使用应用程序代码 (PHP) 或数据库触发器来构建和维护聚合表,但我希望在查询中解决这个问题(部分是因为我希望它优雅,部分是因为我很好奇怎么做)。如果我能做到这一点,我就可以缓存结果或类似的东西。
到目前为止,我能够获得这样的单一状态的结果:
SELECT
pv.created_at_date,
(
SELECT CONCATcount(*)
FROM `product_versions` p
JOIN (
SELECT product_id, MAX(id) AS latest_version
FROM product_versions
GROUP BY product_id
) grouped_versions ON p.product_id = grouped_versions.product_id AND p.id = grouped_versions.latest_version
WHERE created_at_date = pv.created_at_date
AND status = 'draft'
ORDER BY id ASC
) as draft_status_count_subquery,
FROM product_versions pv
WHERE created_at_date >= date_sub(now(), interval 7 day)
GROUP BY pv.created_at_date
ORDER BY pv.created_at_date desc
结果:
+-----------------+-----------------------------+
| created_at_date | draft_status_count_subquery |
+-----------------+-----------------------------+
| 2013-09-09 | 0 |
| 2013-09-06 | 26 |
| 2013-09-05 | 40 |
| 2013-09-04 | 46 |
+-----------------+-----------------------------+
需要注意的是,我需要能够确定每天最新版本的状态(使用 grouped_versions 子查询)才能返回正确的聚合。
我所有其他加入其他状态的尝试都没有奏效(除了明显的是为每个我不愿意做的状态添加额外的子查询(status_count_subquery 1 .. n),因为性能已经很慢了1 个子查询)。
因此,我问外面的世界,有没有更好的方法来实现这个结果(或类似的)?
测试数据
以下是一些用于重新创建场景的示例数据:
CREATE TABLE `product_versions` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(10) unsigned DEFAULT NULL,
`created_at_date` date DEFAULT NULL,
`title` varchar(100) DEFAULT NULL,
`status` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
INSERT INTO `product_versions` (`id`, `product_id`, `created_at_date`, `title`, `status`)
VALUES
(1, 1, '2013-09-06', 'Foo Product', 'draft'),
(2, 1, '2013-09-06', 'Foo Product', 'active'),
(3, 2, '2013-09-06', 'Bar Product', 'draft'),
(4, 1, '2013-09-07', 'Foo Product', 'archived'),
(5, 2, '2013-09-07', 'Bar Product', 'active'),
(6, 3, '2013-09-07', 'Baz Product', 'draft'),
(7, 4, '2013-09-07', 'Fiz Product', 'draft');
希望有这样的输出
+-----------------+-------+--------+----------+
| created_at_date | draft | active | archived |
+-----------------+-------+--------+----------+
| 2013-09-07 | 2 | 1 | 1 |
| 2013-09-06 | 1 | 1 | 0 |
+-----------------+-------+--------+----------+