Сортировать, чтобы иметь непоследовательные значения столбца - PullRequest
0 голосов
/ 23 октября 2018

возможно ли это в запросах 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

Заранее спасибо.

Ответы [ 4 ]

0 голосов
/ 23 октября 2018

Вот мой алгоритм:

  1. подсчитывать частоту каждого имени
  2. упорядочивать по убыванию частоты и имени
  3. разрезать на разделы до максимальной частоты
  4. количество строк в каждом разделе
  5. порядок по номеру строки и номеру раздела

Пример: имена 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.Перед этим вы можете вернуться к подзапросам, которые сделают один и тот же запрос довольно длинным и трудным для чтения.Я полагаю, вы могли бы также использовать переменные вместо этого, каким-то образом.

Демонстрация скриптов БД: https://www.db -fiddle.com / f / 8amYX6iRu8AsnYXJYz15DF / 1

0 голосов
/ 23 октября 2018

Следующее решение будет работать для всех версий MySQL , особенно версии <8.0 </strong>

  • В производной таблице , сначалаотсортируйте вашу фактическую таблицу, используя name и id.
  • Затем определите номер строки для конкретной строки во всех строках, имеющих одинаковое значение name.
  • Теперь,используйте этот набор результатов и сортируйте его по значениям номер строки .Итак, все строки, имеющие номер строки = 1 , будут на первом месте (для всех различных значений name) и так далее.Следовательно, последовательные 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Скрипка ДЕМО

0 голосов
/ 23 октября 2018

Другая идея ...

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 |
+----+--------+
0 голосов
/ 23 октября 2018

В MySQL 8+ вы можете сделать:

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

В более ранних версиях вы можете сделать это с помощью переменных.

...