Sort to have non-consecutive column values

核能气质少年 提交于 2019-12-11 15:44:19

问题


is this possible in mysql queries? Current data table is:

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

In the name column, i would like to sort it so there is no consecutive name on my select query.

My desires output would be, no consecutive george in name column.

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

Thanks in advance.


回答1:


In MySQL 8+, you can do:

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

In earlier versions, you can do this using variables.




回答2:


Another idea...

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 |
+----+--------+



回答3:


Following solution would work for all the MySQL versions, especially version < 8.0

  • In a Derived table, first sort your actual table, using name and id.
  • Then, determine the row number for a particular row, within all the rows having same name value.
  • Now, use this result-set and sort it by the row number values. So, all the rows having row number = 1 will come first (for all the different name value(s)) and so on. Hence, consecutive name rows wont appear.

You can try the following using User-defined Session Variables:

SELECT dt2.id,
       dt2.fruit,
       dt2.name
FROM   (SELECT @row_no := IF(@name_var = dt1.name, @row_no + 1, 1) AS row_num,
               dt1.id,
               dt1.fruit,
               @name_var := dt1.name                               AS name
        FROM   (SELECT id,
                       fruit,
                       name
                FROM   your_table_name
                ORDER  BY name,
                          id) AS dt1
               CROSS JOIN (SELECT @row_no := 0,
                                  @name_var := '') AS user_init_vars) AS dt2
ORDER  BY dt2.row_num,
          dt2.id  

DB Fiddle DEMO




回答4:


Here is my algorithm:

  1. count each name's frequency
  2. order by frequency descending and name
  3. cut into partitions as large as the maximum frequency
  4. number rows within each partition
  5. order by row number and partition number

An example: Names A, B, C, D, E

 step 1 and 2
 ------------
 AAAAABBCCDDEE

 step 3 and 4
 ------------
 12345     
 AAAAA
 BBCCD
 DEE

 step 5
 ------
 ABDABEACEACAD

The query:

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);

Common table expression (WITH clauses) and window functions (aggregation OVER) are available as of MySQL 8 or MariaDB 10.2. Before that you can retreat to subqueries, which will make the same query quite long and hard to read, though. I suppose you could also use variables instead, somehow.

DB fiddle demo: https://www.db-fiddle.com/f/8amYX6iRu8AsnYXJYz15DF/1



来源:https://stackoverflow.com/questions/52948761/sort-to-have-non-consecutive-column-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!