[英]MySQL COUNT and GROUP BY subquery
I'm trying to find the count of posts grouped by branch and category. 我正在尝试查找按分支和类别分组的帖子数。 I'm not getting the categories with count 0.
我没有得到计数为0的类别。
CREATE TABLE branches
(`id` serial primary key, `name` varchar(7) unique)
;
INSERT INTO branches
(`id`, `name`)
VALUES
(1, 'branch1'),
(2, 'branch2'),
(3, 'branch3')
;
CREATE TABLE categories
(`id` serial primary key, `category` varchar(4) unique)
;
INSERT INTO categories
(`id`, `category`)
VALUES
(1, 'cat1'),
(2, 'cat2')
;
CREATE TABLE posts
(`id` serial primary key, `branch_id` int, `category_id` int, `title` varchar(6), `created_at` varchar(10))
;
INSERT INTO posts
(`id`, `branch_id`, `category_id`, `title`, `created_at`)
VALUES
(1, 1, 1, 'Title1', '2017-12-14'),
(2, 1, 2, 'Title2', '2018-01-05'),
(3, 2, 1, 'Title3', '2018-01-10')
;
Expected Output: 预期产量:
+---------+----------+----+----+
| branch | category | c1 | c2 |
+---------+----------+----+----+
| branch1 | cat1 | 1 | 0 |
| branch1 | cat2 | 0 | 1 |
| branch2 | cat1 | 0 | 1 |
| branch2 | cat2 | 0 | 0 |
+---------+----------+----+----+
Query tried: 查询尝试:
SELECT b.name, x.c1, y.c2 FROM branches b
LEFT JOIN (
SELECT COUNT(id) c1 FROM posts WHERE created_at < '2018-01-01'
GROUP BY posts.branch_id, posts.category_id
) x x.branch_id = b.id
LEFT JOIN (
SELECT COUNT(id) c2 FROM posts WHERE created_at BETWEEN '2018-01-01' AND '2018-01-31'
GROUP BY posts.branch_id, posts.category_id
) y y.branch_id = b.id
GROUP BY b.id
It looks like this might do what you want. 看来这可能会做您想要的。
Explanation: Get each possible combination of branch/category for branches which exists in posts. 说明:获取帖子中存在的分支的分支/类别的每种可能组合。 Do a conditional sum to get the counts by date range and branch/category.
进行条件求和,以按日期范围和分支/类别获取计数。 Then join back to branch.
然后加入分支。
SELECT b.b_id branch,
b.category,
COALESCE(Range_Sum.C1,0) C1,
COALESCE(Range_Sum.C2,0) C2
FROM ( SELECT b.id b_id,
c.id c_id,
c.category
FROM branches b,
categories c
WHERE EXISTS
( SELECT 1
FROM posts
WHERE b.id = posts.branch_id
)
) b
LEFT
JOIN (SELECT p.branch_id,
c.id c_id,
c.category,
SUM
( CASE WHEN p.created_at < '2018-01-01' THEN 1
ELSE 0
END
) C1,
SUM
( CASE WHEN p.created_at BETWEEN '2018-01-01' AND '2018-01-31' THEN 1
ELSE 0
END
) C2
FROM posts p
INNER
JOIN categories c
ON p.category_id = c.id
GROUP
BY p.branch_id,
c.category,
c.id
) Range_Sum
ON b.b_id = Range_Sum.branch_id
AND b.c_id = Range_Sum.c_id;
Also, just a thing for writing easily readable queries - NEVER use x and y as aliases. 而且,这只是编写易于阅读的查询的内容-切勿使用x和y作为别名。 Choose anything else that could possibly be more informative.
选择其他可能更有用的信息。
You need to CROSS JOIN branches
and categories
first; 您需要首先CROSS JOIN
branches
和categories
; then LEFT JOIN to posts
and do conditional counts based on your WHERE criteria. 然后LEFT JOIN
posts
并根据您的WHERE标准进行条件计数。
Generic format: 通用格式:
SELECT x.data, y.data
, COUNT(CASE WHEN conditionN THEN 1 ELSE NULL END) AS cN
FROM x CROSS JOIN y
LEFT JOIN z ON x.id = z.x_id AND y.id = z.y_id
GROUP BY x.data, y.data
;
Note: COUNT (and pretty much all aggregate functions) ignore NULL values. 注意:COUNT(几乎所有聚合函数)都会忽略NULL值。
Maybe a little contrived... 也许有点人为...
SELECT DISTINCT x.branch_id
, y.category_id
, COALESCE(z.created_at < '2018-01-01',0) c1
, COALESCE(z.created_at BETWEEN '2018-01-01' AND '2018-01-31',0) c2
FROM posts x
JOIN posts y
LEFT
JOIN posts z
ON z.branch_id = x.branch_id
AND z.category_id = y.category_id;
http://sqlfiddle.com/#!9/8aabf2/31 http://sqlfiddle.com/#!9/8aabf2/31
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.