2016-09-20 42 views
1

我有父母posts表和孩子votesposts.idvotes.post_id的关系。我想统计每个职位的平均评分,但只有最新的50票。我知道该怎么做,对于所有投票:每位家长的平均条件为

SELECT T1.`title`, (
    SELECT AVG(`vote`) 
    FROM `votes` 
    WHERE `votes`.`post_id` = T1.`id` 
) AS `average` 
FROM `posts` T1 
GROUP BY T1.`id` 

我知道这可能是与子查询:

SELECT T1.`title`, (
    SELECT AVG(`vote`) 
    FROM (
     SELECT `vote` FROM `votes` 
     WHERE `votes`.`post_id` = T1.`id` 
     ORDER BY `votes`.`id` DESC 
     LIMIT 10 
    ) AS T2 
) AS `average` 
FROM `posts` T1 
GROUP BY T1.`id` 

但有错误:Error in query (1054): Unknown column 'T1.id' in 'where clause'。在子查询中不能访问T1别名。有任何想法吗?

http://sqlfiddle.com/#!9/fb9341/2

回答

1

好吧,你要挑选在每个职位最新的50行的行。这种类型的查询有很多堆栈溢出的答案,主要是在标签下。例如:How to SELECT the newest four items per category?

一旦您编写了该查询,您可以将其放入像您已经知道如何编写的子查询中,以获得每个帖子的AVG(vote)


回复您的评论:

这就是我的意思是:鉴于您的SQLFiddle数据

SELECT T1.title, AVG(V.vote) AS avg_vote 
FROM posts T1 
JOIN (
    SELECT v1.id, v1.post_id, v1.vote 
    FROM votes v1 
    LEFT OUTER JOIN votes v2 ON v1.post_id = v2.post_id and v1.id < v2.id 
    GROUP BY v1.id 
    HAVING COUNT(*) < 10 
) AS V ON T1.id = V.post_id 
GROUP BY T1.id; 

输出:

+---------+----------+ 
| title | avg_vote | 
+---------+----------+ 
| Title 1 | 5.4000 | 
| Title 2 | 4.2000 | 
+---------+----------+ 

为了帮助在子查询的JOIN ,你应该在列上有votes的索引(post_id,id)。


这里的另一个解决方案,而无需唯一列工作:

SELECT T1.title, AVG(V.vote) AS avg_vote 
FROM posts T1 
JOIN (
    SELECT * 
    FROM (
     SELECT v.*, @r := IF(@p = post_id, @r+1, 1) AS rownum, @p := post_id 
     FROM (SELECT @p:=null, @r:=0) AS _init 
     CROSS JOIN votes v 
     ORDER BY v.post_id, v.id DESC 
    ) AS t 
    WHERE t.rownum <= 10 
) AS V ON T1.id = V.post_id 
GROUP BY T1.id; 

输出是一样的事先查询。

+0

是的,但我仍然需要将别名传递给子查询,因为'AVG'会创建额外的子查询。 – hlcs

+0

不,你不知道。在不参考外部查询的情况下,按照'votes.post_id'进行前50个查询。将它作为'FROM'子句中的子查询来完成。然后将其加入'posts'表。 –

+0

我做到了这一点,它非常缓慢的4.5秒。 – hlcs