(
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id )
FROM root_tags
LEFT JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
LEFT JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
LEFT JOIN root_granted ON ( root_granted.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND root_granted.mem_id = '3'
GROUP BY root_tags.tag_id
ORDER BY 3 DESC
)
UNION
(
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id )
FROM root_tags
LEFT JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
LEFT JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND NOT EXISTS (
SELECT *
FROM root_granted
WHERE root_granted.pg_id = root_pages.pg_id )
GROUP BY root_tags.tag_id
ORDER BY 3 DESC
)
上面的查询返回如下结果,
tag_id tag_name COUNT(root_tags.tag_id)
16 expert-category-c 2
14 expert-category-a 1
15 expert-category-b 1
16 expert-category-c 1
正如您所看到的 tag_id 16
是重复的,我如何重写查询以使 tag_id 16
的计数为 3
,我的意思是我希望查询返回这样的结果,
tag_id tag_name COUNT(root_tags.tag_id)
16 expert-category-c 3
14 expert-category-a 1
15 expert-category-b 1
我尝试使用此查询,但它返回错误...
(
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id )
FROM root_tags
LEFT JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
LEFT JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
LEFT JOIN root_granted ON ( root_granted.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND root_granted.mem_id = '3'
)
UNION
(
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id )
FROM root_tags
LEFT JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
LEFT JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND NOT EXISTS (
SELECT *
FROM root_granted
WHERE root_granted.pg_id = root_pages.pg_id )
)
GROUP BY root_tags.tag_id
ORDER BY 3 DESC
您能告诉我如何完成这项工作吗?
谢谢。
最佳答案
在分析您的实际查询后,下面进一步给出了更好的查询。
您可以使用 UNION ALL 而不是 UNION 合并两个查询(以保留重复项),然后在整个集合中运行 GROUP BY。
SELECT tag_id, tag_name, SUM(CountTags) as CountTags
FROM
(
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id ) CountTags
FROM root_tags
LEFT JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
LEFT JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
LEFT JOIN root_granted ON ( root_granted.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND root_granted.mem_id = '3'
GROUP BY root_tags.tag_id
UNION ALL
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id ) CountTags
FROM root_tags
LEFT JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
LEFT JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND NOT EXISTS (
SELECT *
FROM root_granted
WHERE root_granted.pg_id = root_pages.pg_id )
GROUP BY root_tags.tag_id
) SQ
GROUP BY tag_id, tag_name
ORDER BY CountTags DESC
由于您的 WHERE 子句针对 root_granted 和 root_pages 进行过滤,因此这些实际上是 INNER JOIN。您还可以使用 EXISTS 测试来模拟 UNION 的第一部分,假设每个 root_pages 记录永远不能拥有超过 1 个 root_granted 记录。
SELECT root_tags.tag_id, root_tags.tag_name, COUNT( root_tagged.pg_id ) CountTags
FROM root_tags
INNER JOIN root_tagged ON ( root_tagged.tag_id = root_tags.tag_id )
INNER JOIN root_pages ON ( root_pages.pg_id = root_tagged.pg_id )
WHERE root_pages.parent_id = '5'
AND (NOT EXISTS (
SELECT *
FROM root_granted
WHERE root_granted.pg_id = root_pages.pg_id )
OR EXISTS (
SELECT *
FROM root_granted
WHERE root_granted.pg_id = root_pages.pg_id AND root_granted.mem_id = '3'))
GROUP BY root_tags.tag_id, root_tags.tag_name
ORDER BY CountTags DESC
由于 not contains
和 exists
是互斥的,因此您可以使用 OR 将它们组合起来进行单个查询。
关于sql - MySQL:联合、计数和分组依据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4952041/