【问题标题】:MySQL: Ordering By Using Two Counts From Another Table?MySQL:使用另一个表中的两个计数进行排序?
【发布时间】:2011-08-13 01:46:39
【问题描述】:

我有一个名为“posts”的 sql 表,看起来像这样:

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

还有一个名为“votes”的方法,它存储“posts”表中帖子的赞成票或反对票:

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

在此表中,“类型”为 0(表示反对票)或 1(表示赞成票)。

我将如何按帖子的(赞成 - 反对)数量按“蒂姆”排序帖子?

【问题讨论】:

  • 基本上,Tim 的第一个帖子 (id=0) 有 2 个赞成票和 1 个反对票,所以得分为 1。而他的第二个帖子 (id=1) 没有任何票数,所以它有一个零分。所以目标是,当这些被选中时(SELECT * FROM posts WHERE user='tim' ORDER BY <post score> DESC),我们可以以某种方式按分数排序,而无需在帖子表中添加新字段

标签: mysql sql sql-order-by


【解决方案1】:
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

更新 - pv 解释。

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

在继续解释表别名之前,我将简要解释为什么您可能需要在列名前加上表名前缀,例如 posts.id 而不是 id。基本上,当一个查询引用多个表时,例如在这种情况下,您可能会发现在列名前加上相应的表名总是非常有用的。这样,当您重新访问旧脚本时,您总是可以知道哪个列属于哪个表,而无需查找所引用表的结构。此外,在省略表引用时包含表引用是强制,这会导致列属于哪个表的歧义。 (在这种情况下,引用id 列而不引用posts 表确实会产生模棱两可的情况,因为每个表都有自己的id。)

现在,当您在列名之前写出完整的表名时,可能难以阅读大型而复杂的查询。这就是(短)别名派上用场的地方:它们使查询更易于阅读和理解,尽管我已经了解到并非所有人都同意这种观点,因此您应该自己判断:this question 包含两个版本同一个查询,一个带有长名称的表引用,另一个带有短别名的,以及一个意见(在对其中一个答案的评论中)为什么别名不适合。

无论如何,在此特定查询中使用短表别名可能不如在某些更复杂的语句中有用。只是我习惯于查询引用多个表时给表起别名。

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

【讨论】:

  • 我喜欢你用来确定投票值的操作——它很可爱,很好
  • @Derek:谢谢。但是,如果存在/出现其他类型,它可能会中断。但我将其保留原样,作为更传统(且可靠)的 CASE/IF() 方法的替代方案。
  • @Andiry M:抱歉,我正在学习 SQL,如果你能澄清一下这些单个字母的作用(pv),我将不胜感激,他们只是添加快速引用这些表格的方法?你能把我链接到一个教程或告诉我它们叫什么吗?谢谢。
  • @Tomas:基本上,是的,为了简洁起见,它们被用来代替完整的名称。我添加了一个解释。
【解决方案2】:

未经测试,但应该可以工作:

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 吗? ;-)

【讨论】:

    【解决方案3】:

    编辑:我删除了子查询,因为在 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
    

    【讨论】:

    • 我已经更新了它——我对 mssql 更熟悉,所以我写了一些可以移植的东西。更新后的查询应该更适合 mysql
    • @Derek:那么您可能还不知道 SQL Server 在 ORDER BY 中也支持别名引用。 +1 用于旧的和跨平台的 CASE 方法,但 @-names 可能应该替换为“正常”的。
    • @andriy 哇,我今天刚学到新东西……谢谢,我不知道
    猜你喜欢
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多