【问题标题】:Query to ORDER BY the number of rows returned from another SELECT查询 ORDER BY 从另一个 SELECT 返回的行数
【发布时间】:2013-11-26 23:12:46
【问题描述】:

我正在尝试围绕 SQL 进行思考,我需要一些帮助来弄清楚如何在 PostgreSQL 9.3 中执行以下查询。

我有一个 users 表和一个 friends 表,其中在多行中列出了用户 ID 和朋友的用户 ID。

我想查询用户表,并按共同好友的数量对一个用户ID进行排序。

因此,friends 表如下所示:

user_id | friend_user_id
1       | 4
1       | 5
2       | 10
3       | 7

以此类推,所以用户 1 将 4 和 5 列为好友,而用户 2 将 10 列为好友,所以我想按用户 1 在friend_user_id 中的最高计数排序,以得到user_id 中的结果选择。

【问题讨论】:

  • 请发布您的表格架构和您想要的排序输出类型的示例。

标签: sql postgresql sql-order-by left-join aggregate-functions


【解决方案1】:

Postgres 的做法:

SELECT *
FROM   users u
LEFT   JOIN (
   SELECT user_id, count(*) AS friends
   FROM   friends
   ) f USING (user_id)
ORDER  BY f.friends DESC NULLS LAST, user_id  -- as tiebreaker
  • 关键字AS 只是表别名的噪音。但不要从列别名中省略它。 "Omitting the AS Key Word"上的手册:

    FROM 项中,标准和PostgreSQL 都允许省略AS 在作为非保留关键字的别名之前。但这不切实际 用于输出列名,因为语法不明确

    我的大胆强调。

  • ISNULL() 是 MySQL 或 SQL Server 的自定义扩展。 Postgres 使用 SQL 标准函数 COALESCE()。但是这里也不需要。请改用NULLS LAST 子句,这样更快更简洁。见:

  • 多个用户将拥有相同数量的朋友。这些对等点将被任意排序。重复执行可能会产生不同的排序顺序,这通常是不可取的。将更多表达式添加到ORDER BY 作为决胜局。最终,主键解决了任何剩余的歧义。

  • 如果两个表共享相同的列名user_id(就像他们应该的那样),您可以在连接子句中使用语法快捷方式USING。另一个标准 SQL 功能。欢迎的副作用:user_id 仅在 SELECT * 的输出中列出一次,而不是在加入 ON 时。许多客户端甚至不接受输出中的重复列名。

【讨论】:

    【解决方案2】:

    这样的?

    SELECT * FORM [users] u
    LEFT JOIN (SELECT user_id, COUNT(*) friends FROM fields) f
    ON u.user_id = f.user_id
    ORDER BY ISNULL(f.friends,0) DESC
    

    【讨论】:

    • 除了PostgreSQL中没有ISNULL之外,那是MySQL主义。标准 SQL 使用 COALESCE
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 2011-09-17
    相关资源
    最近更新 更多