如何在不重复子查询的情况下选择所有这些数据?

时间:2012-03-02 20:47:39

标签: mysql

假设我有一个名为'users'的表,一个名为'posts'的表和一个名为'ratings'的表,它存储每个帖子的每个用户的评级。如果我想选择帖子,连同他们的大拇指,拇指向下和'平均'评级(四舍五入到小数点后第二位),我会这样做:

SELECT *,
    (SELECT COUNT(*) FROM ratings WHERE thumb='up' AND post_id = posts.id) AS thumbs_up,
    (SELECT COUNT(*) FROM ratings WHERE thumb='down' AND post_id = posts.id) AS thumbs_down,
    ROUND((SELECT COUNT(*) FROM ratings WHERE thumb='up' AND post_id = posts.id) / (SELECT COUNT(*) FROM ratings WHERE post_id = posts.id), 2) AS average_rating
FROM posts;

但有没有办法在不重复子查询的情况下获取相同的数据?我的意思是,理想情况下我想这样做:

SELECT *,
    (SELECT COUNT(*) FROM ratings WHERE thumb='up' AND post_id = posts.id) AS thumbs_up,
    (SELECT COUNT(*) FROM ratings WHERE thumb='down' AND post_id = posts.id) AS thumbs_down,
    ROUND(thumbs_up / (thumbs_up + thumbs_down), 2) AS average_rating
FROM posts;

但MySQL不允许这样做。什么是下一个最好的事情?或者是否有更好的方法,使用JOIN或UNION?

3 个答案:

答案 0 :(得分:3)

SELECT
    *,
    ROUND(thumbs_up / (thumbs_up + thumbs_down), 2) AS average_rating
FROM (
    SELECT
        YourColumns...
        SUM(CASE WHEN r.thumb = 'up' THEN 1 END) AS thumbs_up,
        SUM(CASE WHEN r.thumb = 'down' THEN 1 END) AS thumbs_down
    FROM
        posts p LEFT JOIN
        ratings r ON r.post_id = p.id
    GROUP BY YoursColumns
) sub

答案 1 :(得分:0)

您可以简单地在存储过程中使用变量。代码是概念,可能需要调整以适应mysql。

SET @thumbsup = 0;
SET @thumbsdown = 0;

SELECT @thumbsup = COUNT( * ) FROM ratings WHERE thumb = 'up' AND post_id = @someid;
SELECT @thumbsdown = COUNT( * ) FROM ratings WHERE thumb = 'down' AND post_id = @someid;

RETURN @thumbsup, @thumbsdown, ROUND( @thumbsup / ( thumbsup + thumbsdown ), 2 );

答案 2 :(得分:0)

为什么不在你的“帖子”表格中列出“ups”和“down”,在哪里汇总/计算起伏?你会以这样的结局结束:

SELECT ups, downs, ROUND(ups / (ups + downs), 2) AS average_rating FROM posts where id = anId;