【问题标题】:How make random order in each group of rows in one sql query?如何在一个 sql 查询中对每组行进行随机排序?
【发布时间】:2021-01-23 05:55:35
【问题描述】:

我有表 'stock'(MariaDB 数据库),其中包含产品列表。每个产品都有 ID、标题、价格和数量。 有些产品的金额 > 0 且价格=0,这意味着价格未定义。有些产品定义了价格(价格>0),但金额=0。第三组价格>0,金额>0。

我想从这个表中按这样的顺序选择产品

  1. 价格>0且金额>0的产品
  2. 价格>0且金额=0的产品
  3. 价格=0且金额>0的产品

这 3 个组中的每一个都必须具有随机的行顺序。不是查询中所有行的随机顺序,而是每个组中的随机顺序,保留组的顺序 - 1, 2, 3

这个 sql 查询应该是什么样子?

【问题讨论】:

    标签: mysql sql mariadb sql-order-by


    【解决方案1】:

    在 MySQL/MariaDB 中,您可以将逻辑简化为:

    order by (price > 0) desc, (amount > 0) desc
    

    在这些数据库中,布尔表达式首先按“false”排序,然后按“true”排序(因为 false --> 0 和 true --> 1)。因此,desc 完全符合您的要求:首先是有效价格,然后是有效金额。

    【讨论】:

      【解决方案2】:

      您可以使用条件排序:

      select *
      from stock
      order by 
          case 
              when price > 0 and amount > 0 then 1
              when price > 0 and amount = 0 then 2
              when price = 0 and amount > 0 then 3
              else 4
          end,
          rand()
      

      【讨论】:

      • 不符合这三个条件的记录怎么办?可以在案例条件中添加else 4 部分吗?
      • @SlavaRozhnev: 那么case 表达式返回null,它排在最后,因为我们使用升序。所以需要一个else 分支。旁注:您的答案不起作用:首先,您需要在每个成员周围加上括号,即便如此,也不能保证最终结果中的行顺序。 Documentation对单个 SELECT 语句使用 ORDER BY 并不意味着行在最终结果中出现的顺序,因为默认情况下 UNION 会产生一组无序的行
      • 你说得对,我刚刚删除了它。我还测试了使用 NULL 值的排序:MySQL 和 MariaDB 在 ASC 排序中将 NULL 放在首位,PostgreSQL 在列表末尾设置 NULL。 sqlize.online/…
      • @SlavaRozhnev:啊,是的,你是对的(我认为 Postgres 遵循 ANSI 标准,但显然不是 MySQL)。固定的。谢谢。
      【解决方案3】:

      你可以像这样对它们进行排序:

      order by 
        price > 0 and amount > 0 desc,
        price > 0 and amount = 0 desc,
        price = 0 and amount > 0 desc,
        rand()
      

      因为order by 子句中的每个布尔表达式对于truefalse 的计算结果为1 或0。

      或者涉及一些数学:

      order by 
        10 * (price > 0) + (amount > 0) desc,
        rand()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-15
        • 2013-01-28
        • 1970-01-01
        • 1970-01-01
        • 2014-11-15
        • 1970-01-01
        • 2011-07-15
        • 2012-07-03
        相关资源
        最近更新 更多