Mysql 排序为具有非连续的列值

Mysql 排序为具有非连续的列值,mysql,sql,algorithm,sorting,columnsorting,Mysql,Sql,Algorithm,Sorting,Columnsorting,这在mysql查询中可能吗?当前数据表为: id - fruit - name 1 - Apple - George 2 - Banana - George 3 - Orange - Jake 4 - Berries - Angela 在name列中,我想对其进行排序,以便在我的select查询中没有连续的名称 我的期望输出是,名称列中没有连续的george id - fruit - name 1 - Apple - George 3 - Orange - Jake 2 - Banana -

这在mysql查询中可能吗?当前数据表为:

id - fruit - name
1 - Apple - George
2 - Banana - George
3 - Orange - Jake
4 - Berries - Angela
name
列中,我想对其进行排序,以便在我的
select
查询中没有连续的名称

我的期望输出是,名称列中没有连续的
george

id - fruit - name
1 - Apple - George
3 - Orange - Jake
2 - Banana - George
4 - Berries - Angela

提前感谢。

在MySQL 8+中,您可以执行以下操作:

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

在早期版本中,可以使用变量执行此操作。

在MySQL 8+中,可以执行以下操作:

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

在早期版本中,您可以使用变量来执行此操作。

以下解决方案适用于,尤其是版本<8.0

  • 在a中,首先使用
    name
    id
    对实际表进行排序
  • 然后,在具有相同
    名称
    值的所有行中,确定特定行的行号
  • 现在,使用此结果集并按行数对其排序。因此,行号为1的所有行将首先出现(对于所有不同的
    name
    value),依此类推。因此,不会出现连续的
    name
您可以使用以下命令尝试以下操作:


以下解决方案适用于,尤其是版本<8.0

  • 在a中,首先使用
    name
    id
    对实际表进行排序
  • 然后,在具有相同
    名称
    值的所有行中,确定特定行的行号
  • 现在,使用此结果集并按行数对其排序。因此,行号为1的所有行将首先出现(对于所有不同的
    name
    value),依此类推。因此,不会出现连续的
    name
您可以使用以下命令尝试以下操作:

另一个想法

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,name VARCHAR(12) NOT NULL
);

INSERT INTO my_table VALUES
(1,'George'),
(2,'George'),
(3,'Jake'),
(4,'Angela');

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

+----+--------+
| id | name   |
+----+--------+
|  1 | George |
|  3 | Jake   |
|  4 | Angela |
|  2 | George |
+----+--------+
如果存在my_表,则删除表;
创建表格my_表格
(id)串行主键
,名称VARCHAR(12)不为空
);
在my_表中插入值
(1,“乔治”),
(2,“乔治”),
(3,“杰克”),
(4,“安吉拉”);
选择x.*
从我的表x
加入我的桌子
在y.name=x.name上
还有另一个想法

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,name VARCHAR(12) NOT NULL
);

INSERT INTO my_table VALUES
(1,'George'),
(2,'George'),
(3,'Jake'),
(4,'Angela');

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

+----+--------+
| id | name   |
+----+--------+
|  1 | George |
|  3 | Jake   |
|  4 | Angela |
|  2 | George |
+----+--------+
如果存在my_表,则删除表;
创建表格my_表格
(id)串行主键
,名称VARCHAR(12)不为空
);
在my_表中插入值
(1,“乔治”),
(2,“乔治”),
(3,“杰克”),
(4,“安吉拉”);
选择x.*
从我的表x
加入我的桌子
在y.name=x.name上
y.id这是我的算法:

  • 计算每个名字的频率
  • 按频率降序和名称排序
  • 切割成与最大频率一样大的分区
  • 每个分区内的行数
  • 按行号和分区号排序
  • 例如:名称A、B、C、D、E

     step 1 and 2
     ------------
     AAAAABBCCDDEE
    
     step 3 and 4
     ------------
     12345     
     AAAAA
     BBCCD
     DEE
    
     step 5
     ------
     ABDABEACEACAD
    
    查询:

    with counted as
    (
      select id, fruit, name, count(*) over (partition by name) as cnt
      from mytable 
    )
    select id, fruit, name
    from counted
    order by
      (row_number() over (order by cnt desc, name) - 1) % max(cnt) over (),
      row_number() over (order by cnt desc, name);
    
    从MySQL 8或MariaDB 10.2开始,就可以使用公共表表达式(
    ,带有
    子句)和窗口函数(聚合
    超过
    )。在此之前,您可以退回到子查询,这将使同一查询相当长且难以阅读。我想你也可以用变量来代替

    DB fiddle演示:

    这是我的算法:

  • 计算每个名字的频率
  • 按频率降序和名称排序
  • 切割成与最大频率一样大的分区
  • 每个分区内的行数
  • 按行号和分区号排序
  • 例如:名称A、B、C、D、E

     step 1 and 2
     ------------
     AAAAABBCCDDEE
    
     step 3 and 4
     ------------
     12345     
     AAAAA
     BBCCD
     DEE
    
     step 5
     ------
     ABDABEACEACAD
    
    查询:

    with counted as
    (
      select id, fruit, name, count(*) over (partition by name) as cnt
      from mytable 
    )
    select id, fruit, name
    from counted
    order by
      (row_number() over (order by cnt desc, name) - 1) % max(cnt) over (),
      row_number() over (order by cnt desc, name);
    
    从MySQL 8或MariaDB 10.2开始,就可以使用公共表表达式(
    ,带有
    子句)和窗口函数(聚合
    超过
    )。在此之前,您可以退回到子查询,这将使同一查询相当长且难以阅读。我想你也可以用变量来代替



    DB FIDLE demo:

    有两个单独的查询,进行交替获取。您的MySQL服务器版本是什么?这很难。这与所谓的分类正好相反:-)如果你有安吉拉·乔治呢?没有办法对这四个进行分类,以便将所有的乔治分开。在这种情况下,查询要做什么?崩溃?@MadhurBhaiya 5.5.56-mariab服务器您已将请求标记为“sql”。但您并不是在寻找关于SQL的答案(例如,如何修复SQL查询或如何在SQL中应用算法-您既没有查询,也没有算法)。您正在寻找一种算法。因此,您应该删除与数据库相关的标记,并用“算法”标记替换它们。有两个单独的查询,进行交替获取。您的MySQL服务器版本是什么?这很困难。这与所谓的分类正好相反:-)如果你有安吉拉·乔治呢?没有办法对这四个进行分类,以便将所有的乔治分开。在这种情况下,查询要做什么?崩溃?@MadhurBhaiya 5.5.56-mariab服务器您已将请求标记为“sql”。但您并不是在寻找关于SQL的答案(例如,如何修复SQL查询或如何在SQL中应用算法-您既没有查询,也没有算法)。您正在寻找一种算法。因此,您应该删除与数据库相关的标记,并将其替换为“algorithm”标记。嗨,我正在测试这种方法,但当我测试添加另一个george行时,它仍然显示为连续的@bumbaw,这就是Thorsten。如果相同名称的行比其他行多,则排序将不起作用。在那种情况下很难实现。嗯,好吧,我明白了。我需要使用php操作它,然后将结果保存到另一个数组中。像这样的东西。@bumbaw甚至PHP也帮不上忙。假设你一共有10行,其中乔治有6行。你如何融入所有乔治的名字,这样他们就不会consecutive@bumbumpaw:你改过的小提琴说明了为什么这么难。对三个乔治、一个杰克和一个安吉拉进行排序的唯一解决办法是让杰克和安吉拉排第2排和第4排。然而,仅仅从数据库的角度来看,杰克就像安吉拉;它们在表中都有一行,那么应用什么规则来生成一行2和一行4呢?你真正需要的是a