2011-08-13 27 views
3

我有一个SQL表看起来像这样所谓的“上岗”:MySQL:通过从另一个表中使用两个计数来排序?

id | user 
-------------------------------- 
0 | tim 
1 | tim 
2 | bob 

而另一家名为“票”,用于存储无论是在“上岗”表上的职位upvotes或downvotes:

id | postID | type 
-------------------------------- 
0 | 0  | 0 
1 | 2  | 1 
2 | 0  | 1 
3 | 0  | 1 
4 | 3  | 0 

在此表中,“类型”是downvote的0或upvote的1。

我该如何去订阅“tim”发布帖子的数量(upvotes - downvotes)的帖子?

+0

从本质上讲,蒂姆的第一篇文章('ID = 0')有2个upvotes和1个downvote,这样的比分是1。虽然他的第二个职位('ID = 1')没有任何选票,因此得分为零。所以我们的目标是,当这些被选中('SELECT * FROM posts WHERE user ='tim'ORDER BY DESC')时,我们可以按某种方式排序,而不需要在帖子表中添加一个新字段 – Tomas

回答

3
SELECT 
    p.id, 
    p.user, 
    SUM(v.type * 2 - 1) AS votecount 
FROM posts p 
    LEFT JOIN votes v ON p.id = v.postID 
WHERE p.user = 'tim' 
GROUP BY p.id, p.user 
ORDER BY votes DESC 

UPDATE - pv解释。

在该查询中,pv别名分别的,postsvotes。别名本质上是一个替代名称,它只在声明它的语句的范围内(在本例中为SELECT语句)定义。不仅表格可以有别名,而且也可以有列。在此查询中,votecount是由SUM(v.type * 2 - 1)表达式表示的列的别名。但目前我们只谈论桌子。

在继续关于表别名的解释之前,我将简要解释为什么您可能需要在列名前加上表名,如posts.id而不是id。基本上,当查询引用多个表时,就像在这种情况下一样,您可能会发现始终将列名与相应的表名前缀相当有用。这样,当你重新访问一个旧脚本时,你总是可以知道哪个列属于哪个表,而不必查找引用表的结构。此外,它是强制性的在包含表引用时忽略它会造成该列所属的表的歧义。 (在这种情况下,引用id列不必引用posts表并创建模棱两可的情况,因为每个表都有了自己的id。)

现在,一个庞大而复杂的查询可能是困难的,当你写出完整的阅读列名之前的表名。这是短的别名派上用场:他们使查询更容易阅读和理解,虽然我已经知道并非所有人都同意这个观点,所以你应该自己判断:this question包含两个版本查询,其中一个使用长命名表引用,另一个使用短名称引用,以及一个意见(在对其中一个答案的评论中)为什么别名不适用。

无论如何,在这个特定查询中使用短表别名可能并不像在一些更复杂的语句中那样有益。只是当查询引用多个表时,我习惯于对表进行别名。

This MySQL documentation article包含MySQL中用于别名表的官方语法(实际上与标准SQL中的相同)。

+0

我喜欢你的操作来确定投票价值 - 它的可爱,漂亮 –

+0

@Derek:谢谢。但是,如果其他类型存在/出现,它可能会中断。但是我将它保留下来,只是作为更传统(可靠)的CASE/IF()方法的替代方案。 –

+0

@Andiry M:对不起,我正在学习SQL,如果能为我澄清这些单个字母('p'和'v'),我会非常感激,他们是否添加了一种快速引用这些表的方法?你可以将我链接到教程或告诉我他们被称为什么?谢谢。 – Tomas

1

没有测试,但应该工作:

select post.id, sum(if(type = 0, -1, 1)) as score 
from posts join votes on post.id = votes.postID 
where user = 'tim' 
group by post.id 
order by score 

你打算SO同意? ;-)

1

编辑:我砍掉了子查询,因为在mysql中它是不必要的。最初的查询是可移植的,但对于MySQL不是必需的。

select 
    p.id, SUM(case 
       when v.type = 0 then -1 
       when v.type = 1 then 1 
       else 0 end) as VoteCount 
from 
    posts p 
    left join votes v 
     on p.id = v.postid 
where 
    p.[user] = 'tim' 
group by 
    p.id 
order by 
    VoteCount desc 
+0

嗨,德里克,为什么子查询? – TMS

+0

我更新了它 - 我更熟悉mssql,所以我写了一些可移植的东西。更新的查询应该更适合于mysql –

+0

@Derek:那么您可能还不知道SQL Server也支持在ORDER BY中引用别名。对于旧的和跨平台的CASE方法+1,但'@' -names应该可以替换为'正常'的名称。 –

相关问题