【问题标题】:MySQL order by distinct items firstMySQL首先按不同的项目排序
【发布时间】:2020-04-24 08:56:56
【问题描述】:

我有一张物品所有权表,如下所示:

item_possession
===============
id      product_id      status
1       50 (weapon)     available
2       50 (weapon)     unavailable
3       10 (shield)     unavailable
4       10 (shield)     unavailable
5       50 (weapon)     available
6       20 (helmet)     available
7       20 (helmet)     available
8       50 (weapon)     available
9       50 (weapon)     available
10      30 (thunder)    unavailable
11      20 (helmet)     available

注意:这是一个游戏,我可以拥有重复的产品(我可以出售它们),请注意我可以有不同的行引用同一个项目。

是否可以订购我的物品,首先列出不同的物品(我不在乎顺序,我可以使用表格 ID)和最后的重复项?

类似这样的:

item_possession
===============
id      product_id      status
1       50 (weapon)     available
3       10 (shield)     unavailable
6       20 (helmet)     available
8       30 (thunder)    unavailable
2       50 (weapon)     unavailable
4       10 (shield)     unavailable
5       50 (weapon)     available
7       20 (helmet)     available
8       50 (weapon)     available
9       50 (weapon)     available
10      30 (thunder)    unavailable
11      20 (helmet)     available

【问题讨论】:

    标签: mysql sql sql-order-by


    【解决方案1】:

    或者,老派……

    SELECT x.*
      FROM item_possession x 
      JOIN item_possession y 
        ON y.product_id = x.product_id 
       AND y.id <= x.id 
     GROUP 
        BY x.id 
     ORDER 
        BY COUNT(*)
         , id;
    

    编辑:实际上,你似乎想要这个......

    SELECT x.*
      FROM item_possession x 
      LEFT 
      JOIN 
         ( SELECT MIN(id) id FROM item_possession GROUP BY product_id ) y
        ON y.id = x.id
      ORDER 
       BY y.id IS NULL,x.id;
    

    如需更多帮助,请参阅Why should I provide an MCRE for what seems to me to be a very simple SQL query

    【讨论】:

    • 几乎有效!你能解释一下这背后的逻辑吗?唯一的问题是我想要在第一批不同的物品之后的标准订单。您的查询正确返回了第一个项目,但随后它尝试安排以下项目以使它们再次不同。有可能避免这种情况吗?我更新了示例以显示所需的输出!
    • 您的第二个答案完美!你是真正的 SQL 向导 :) 不幸的是我无法完全理解它。
    • 哦,我用各种测试把它拆开,我终于明白了(FALSE = 0 和 TRUE = 1)。你真的是一个 SQL 魔术师!再次感谢!
    【解决方案2】:

    您可以为此使用窗口函数:

    order by row_number() over (partition by product_id order by id)
    

    无需将其放在select 中。您也可以在旧版本中使用子查询来执行此操作:

    order by (select count(*)
              from item_possession t2
              where t2.product_id = t.product_id and t2.id <= t.id
             )
    

    或者,您可以使用变量——这需要两次排序:

    select ip.*
    from (select ip.*,
                 (@rn := if(@p = ip.product_id, @rn + 1,
                            if(@p := ip.product_id, 1, 1)
                           )
                 ) as rn
          from (select ip.* from item_possession ip order by ip.product_id, ip.id
               ) ip cross join
               (select @p := -1, @rn := 0) params
         ) ip
    order by rn, id;
    

    【讨论】:

      【解决方案3】:

      您可以使用row_number()

      select t.*, row_number() over (partition by product_id order by id) as seq
      from table t
      order by seq, id;
      

      【讨论】:

      • 这是给我Syntax error: unexpected '(' (opening parenthesis):select t.*, row_number() over (partition by product_id order by id) as seq from item_possession t order by seq, id;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2013-06-29
      • 2014-01-18
      • 1970-01-01
      相关资源
      最近更新 更多