【问题标题】:How to select comment count, Sum of votes, and whether active user has voted如何选择评论数、投票总和以及活跃用户是否投票
【发布时间】:2016-11-13 19:20:35
【问题描述】:

我在构建 MySQL 查询以返回准确的评论计数、投票总和和活跃用户投票时遇到问题。

我的桌子是

wall_posts ( id, message, username, etc )
comments   ( id, wall_id, username, text, etc )
votes      ( id, wall_id, vote (+1 or -1), username )

我的查询如下所示

SELECT
    wall_posts.*,
    COUNT( comments.wall_id ) AS comment_count,
    COALESCE( SUM( v1.vote ), 0 ) AS vote_tally,
    v2.vote 
FROM
    wall_posts 
    LEFT JOIN comments ON wall_posts.id = comments.wall_id 
    LEFT JOIN votes v1 ON wall_posts.id = v1.wall_id 
    LEFT JOIN votes v2 ON wall_posts.id = v2.wall_id AND v2.username=:username 
WHERE
    symbol =: symbol
GROUP BY
    wall_posts.id
ORDER BY
    date DESC
LIMIT 15

它适用于始终为特定的活跃用户投票(+1 或 -1)返回正确的值,如果没有投票,则返回 null。如果一个项目上没有 cmets,则总票数是正确的。如果有任何 cmets,则投票总和将始终等于评论数,如果有反对票,则可能带有负号,但始终等于 cmets 的数量。

我认为这显然是我连接表格的方式,但我只是无法弄清楚为什么它复制评论计数,1000000 指向可以向我解释这一点的人:)

【问题讨论】:

    标签: mysql count sum left-join


    【解决方案1】:

    您需要在子查询中执行聚合操作。现在,您将 JOIN 将所有表(预聚合)放在一起。如果您删除聚合(和 GROUP BY),您会看到大量数据,但实际上并没有任何意义。

    相反,试试这个(注意我使用的是VIEW):

    CREATE VIEW walls_posts_stats AS
    
    SELECT
        wall_posts.id,
        COALESCE( comments_stats.comment_count, 0 ) AS comment_count,
        COALESCE( votes_stats.vote_tally, 0 ) AS vote_tally
    FROM
    
        wall_posts
    
        LEFT OUTER JOIN
        (
            SELECT
                wall_id,
                COUNT(*) AS comment_count
            FROM
                comments
            GROUP BY
                wall_id
        ) AS comments_stats ON wall_posts.id = comments_stats.wall_id
    
        LEFT OUTER JOIN
        (
            SELECT
                wall_id,
                SUM( vote ) AS vote_tally
            FROM
                votes
            GROUP BY
                wall_id
        ) AS votes_stats ON wall_posts.id = votes_stats.wall_id
    

    然后你可以用你原来的墙数据查询它:

    SELECT
        wall_posts.*, -- note: avoid the use of * in production queries
        stats.comment_count,
        stats.vote_tally,
        user_votes.vote
    FROM
        wall_posts
        INNER JOIN walls_posts_stats AS stats ON wall_posts.id = stats.id
        LEFT OUTER JOIN
        (
            SELECT
                wall_id,
                vote
            FROM
                votes
            WHERE
                username = :username
        ) AS user_votes ON wall_posts.id = user_votes.wall_id
    ORDER BY
        date DESC
    LIMIT 15
    

    假设您可以将它组合成一个大型查询(基本上将 VIEW 正文复制+粘贴到 INNER JOIN walls_posts_stats 子句中),但我认为这会引入可维护性问题。

    虽然 MySQL 确实支持视图,但它不支持参数化视图(也称为可组合的表值函数;存储过程不可组合),这就是 user_votes 子查询不在 walls_posts_stats VIEW 中的原因。

    【讨论】:

    • 嗨,戴,感谢您的回复。它看起来比我想象的要复杂一点! (主要是因为我从未听说过视图,我现在将阅读它们。你会说它不可能在一个查询中做到这一点,就像我有它一样,没有视图。或者是不可能聚合​​,计数和加入所有这在一个声明中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多