这是可能在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)
在早期版本中,你可以使用变量做到这一点。
另一个想法...
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 |
+----+--------+
下面的解决方案会为工作所有的MySQL版本 ,特别版<8.0
- 在派生表 ,第一排序您的实际表,使用
name
和id
。 - 然后,确定用于特定行的行号,具有相同的所有行内的
name
的值。 - 现在,用这个结果集和行号值排序。 所以,具有行数= 1的所有的行会首先(对于所有不同的
name
值(S))等。 因此,连续的name
行不会出现。
您可以尝试使用下面的用户定义的会话变量 :
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小提琴DEMO
这里是我的算法:
- 统计每个名字的频率
- 为了通过频率下降和名称
- 切成一样大的最大频率分区
- 在每个分区内的行数
- 为了通过行号和分区号
一个例子:名称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);
公共表表达式( WITH
子句)和窗函数(聚集OVER
)可作为MySQL的8或MariaDB的10.2。 在此之前,你可以撤退到子查询,这将使相同的查询很长,难以辨认,但。 我想你也可以使用变量来代替,不知何故。
DB小提琴演示: https://www.db-fiddle.com/f/8amYX6iRu8AsnYXJYz15DF/1