Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 按逻辑排序,结果好坏参半?_Mysql_Sql - Fatal编程技术网

Mysql 按逻辑排序,结果好坏参半?

Mysql 按逻辑排序,结果好坏参半?,mysql,sql,Mysql,Sql,我有这个桌子结构 id | status -----+------+ 1 | a | 2 | b | 3 | b | 4 | b | 5 | a | 6 | a | 7 | b | 8 | a | 我有两种状态“a”和“b”。 我需要按照这样的逻辑来排序:对于每两个“a”,显示一个“b”。 类似这样的情况(a更重要,所以如果有很多b,它们最后只会被留下) 有办法做到这一点吗 select

我有这个桌子结构

  id | status
-----+------+
1    | a    |
2    | b    |
3    | b    |
4    | b    |
5    | a    |
6    | a    |
7    | b    |
8    | a    |
我有两种状态“a”和“b”。 我需要按照这样的逻辑来排序:对于每两个“a”,显示一个“b”。 类似这样的情况(a更重要,所以如果有很多b,它们最后只会被留下)

有办法做到这一点吗

select      id
           ,status

from       (select      status
                       ,id
                       ,@prev_status := @status
                       ,@status      := status
                       ,@rn          := case when @prev_status = status 
                                             then @rn + 1 
                                             else 1 
                                        end           as rn

            from        mytable t1,(select @status:=null,@rn:=0) x

            order by    status
                       ,id
            ) t

 order by  floor((rn-1) / case status when 'a' then 2 else 1 end)         
          ,case status when 'a' then 1 else 2 end  
          ,rn
;

这将帮助您了解解决方案:
(组id=
楼层((rn-1)/当“a”时的案例状态,然后是2,否则1结束)


使用变量枚举值,然后使用一些简单的逻辑:

select id, status
from (select t.*,
             (@rn := if(@s = status, @rn + 1,
                        if(@s := status, 1, 1)
                       )
             ) as rn
      from t cross join
           (select @rn := 0, @s := '') params
      where status in ('a', 'b')
      order by status, id
     ) ab
order by (case when status = a then floor( (rn - 1) / 2) else (rn - 1) end),
         status, id;

这应该是MySQL中最快的方法。它对我来说也比相关子查询更清晰,但我承认我对MySQL中的变量有一定的了解。我想这是我第一次看到您使用变量生成行号。我记得,您总是使用相关子查询:-)谢谢!这个解决方案实际上非常有效。虽然我有点问题,但在第一组中我得到了一个额外的“a”:“a b a b a b”Ok能够通过使用@DuduMarkovitz的答案中的“order by”登录来解决上述问题<代码>按楼层订购((rn-1)/案例状态,当“a”时,然后是2,否则1结束)感谢您的解释!虽然它看起来很慢,但我的意思是,我在有20k条记录的桌子上试过了,它运行了几分钟。。最终我需要杀了它戈登对我的answef的模仿可能会更快汉克斯,最终你的答案帮助完成了戈登的答案:)在1M记录上测试,花了几秒钟。你还在吗?
+----+--------+
| id | status |
+----+--------+
|  1 | a      |
|  5 | a      |
|  2 | b      |
|  6 | a      |
|  8 | a      |
|  3 | b      |
|  4 | b      |
|  7 | b      |
+----+--------+
+--------+----+----+----------+
| status | id | rn | group_id |
+--------+----+----+----------+
| a      |  1 |  1 |        0 |
| a      |  5 |  2 |        0 |
| a      |  6 |  3 |        1 |
| a      |  8 |  4 |        1 |
| b      |  2 |  1 |        0 |
| b      |  3 |  2 |        1 |
| b      |  4 |  3 |        2 |
| b      |  7 |  4 |        3 |
+--------+----+----+----------+
select id, status
from (select t.*,
             (@rn := if(@s = status, @rn + 1,
                        if(@s := status, 1, 1)
                       )
             ) as rn
      from t cross join
           (select @rn := 0, @s := '') params
      where status in ('a', 'b')
      order by status, id
     ) ab
order by (case when status = a then floor( (rn - 1) / 2) else (rn - 1) end),
         status, id;