【问题标题】:MySQL: Union, Count, and Group ByMySQL:联合、计数和分组依据
【发布时间】:2011-02-10 00:13:20
【问题描述】:
(
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

您能告诉我如何完成这项工作吗?

谢谢。

【问题讨论】:

    标签: sql mysql count group-by union


    【解决方案1】:

    在分析您的实际查询后,下面会给出更好的查询。

    您可以使用 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 记录的 root_granted 记录不能超过 1 个。

    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 existsexists 是互斥的,您可以使用OR 将它们组合起来进行单个查询。

    【讨论】:

    • 非常感谢您!为什么我不能像你一样写出这么漂亮的代码!!签名...谢谢! :-)
    • UNION ALL 解决方案似乎有一个错误,因为 tag_id 16 返回 2 而 INNER JOINs 返回 3 这是正确的......
    • @lau 修复了 UNION ALL 解决方案,它应该是 SUM(Count) 而不是 COUNT(COUNT)!
    • 谢谢!它现在返回 3!需要一些时间来消化和研究你的代码!非常感谢!
    猜你喜欢
    • 2013-03-10
    • 2016-12-21
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    相关资源
    最近更新 更多