MySQL Выберите несколько столбцов группы по отсортированным значениям столбцов - PullRequest
0 голосов
/ 09 октября 2018

У меня есть эта структура столбцов таблицы:

id - n1 - n2 - n3

И вот она с некоторыми фиктивными данными:

id - n1 - n2 - n3
1 - 3 - 2 - 1
2 - 6 - 5 - 7
3 - 2 - 3 - 1
4 - 1 - 6 - 5
5 - 5 - 6 - 7
6 - 3 - 5 - 6

И идея состоит в том, чтобы выбрать и подсчитать каждую уникальную отдельную группуn1, n2 и n3 в последовательности.

Так, например, мы могли бы получить такой результат:

total - n1s - n2s - n3s
2 - 1 - 2 - 3
2 - 5 - 6 - 7
1 - 1 - 5 - 6
1 - 3 - 5 - 6

Можете ли вы помочь мне установить состояние для достижения этого ??

Я пытаюсь сделать это без множественного выбора и сортировки массива PHP ...

Спасибо.

Ответы [ 3 ]

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

Нам просто нужны выражения, чтобы «отсортировать» значения в столбцах n1, n2 и n3.Если у нас это есть, то мы можем сделать простое GROUP BY и COUNT.

SELECT COUNT(1) AS total
     , IF(t.n1<=t.n2,IF(t.n1<=t.n3,t.n1,t.n3),IF(t.n2<=t.n3,t.n2,t.n3)) AS n1s
     , IF(t.n1<=t.n2,IF(t.n2<=t.n3,t.n2,IF(t.n1<=t.n3,t.n3,t.n1)),IF(t.n1<=t.n3,t.n1,IF(t.n2<=t.n3,t.n3,t.n2 ))) AS n2s
     , IF(t.n1<=t.n2,IF(t.n2<=t.n3,t.n3,t.n2),IF(t.n1<=t.n3,t.n3,t.n1)) AS n3s
  FROM this_table_column_structure t
 GROUP BY n1s,n2s,n3s
 ORDER BY total DESC, n1s, n2s, n3s

вернет

total   n1s   n2s   n3s
-----  ----  ----  ----
    2     1     2     3
    2     5     6     7
    1     1     5     6
    1     3     5     6
0 голосов
/ 10 октября 2018

В качестве первого подхода (если позволяет время), вы действительно должны рассмотреть нормализацию вашей таблицы, как это предлагается в @ 1003 * answer @ Strawberry's

Однако, второй подходможно использовать любое количество столбцов (хотя это неэффективно из-за операций со строками и пузырьковой сортировки), используя определяемые пользователем функции .

Нам в основном необходимо создать функцию, которая может сортировать значения внутристрока, разделенная запятыми.Я нашел рабочую функцию, которая может сделать сортировку.Воспроизведение кода из здесь :

-- sort comma separated substrings with unoptimized bubble sort
DROP FUNCTION IF EXISTS sortString;
DELIMITER |
CREATE FUNCTION sortString(inString TEXT) RETURNS TEXT
BEGIN
  DECLARE delim CHAR(1) DEFAULT ','; -- delimiter 
  DECLARE strings INT DEFAULT 0;     -- number of substrings
  DECLARE forward INT DEFAULT 1;     -- index for traverse forward thru substrings
  DECLARE backward INT;   -- index for traverse backward thru substrings, position in calc. substrings
  DECLARE remain TEXT;               -- work area for calc. no of substrings
-- swap areas TEXT for string compare, INT for numeric compare
  DECLARE swap1 TEXT;                 -- left substring to swap
  DECLARE swap2 TEXT;                 -- right substring to swap
  SET remain = inString;
  SET backward = LOCATE(delim, remain);
  WHILE backward != 0 DO
    SET strings = strings + 1;
    SET backward = LOCATE(delim, remain);
    SET remain = SUBSTRING(remain, backward+1);
  END WHILE;
  IF strings < 2 THEN RETURN inString; END IF;
  REPEAT
    SET backward = strings;
    REPEAT
      SET swap1 = SUBSTRING_INDEX(SUBSTRING_INDEX(inString,delim,backward-1),delim,-1);
      SET swap2 = SUBSTRING_INDEX(SUBSTRING_INDEX(inString,delim,backward),delim,-1);
      IF  swap1 > swap2 THEN
        SET inString = TRIM(BOTH delim FROM CONCAT_WS(delim
        ,SUBSTRING_INDEX(inString,delim,backward-2)
        ,swap2,swap1
        ,SUBSTRING_INDEX(inString,delim,(backward-strings))));
      END IF;
      SET backward = backward - 1;
    UNTIL backward < 2 END REPEAT;
    SET forward = forward +1;
  UNTIL forward + 1 > strings
  END REPEAT;
RETURN inString;
END |
DELIMITER ;

Вам нужно будет запустить этот код на вашем сервере MySQL, чтобы эта функция была доступна в запросе, так же, как встроенные функции MySQL,Теперь запрашивающая часть становится простой.Все, что вам нужно сделать, это Concat_ws() все числовые столбцы через запятую.И затем примените функцию sortString() к объединенной строке.В конце концов, используйте «упорядоченную» строку в предложении Group By, чтобы получить желаемый результат.

Попробуйте:

SELECT sortString(CONCAT_WS(',', n1, n2, n3)) AS n_sequence -- add more columns here
       COUNT(id) AS total 
FROM your_table 
GROUP BY n_sequence 
ORDER BY total DESC 

Теперь я предлагаю использовать код приложения для изменения запятойразделены n_sequence назад к табличному отображению столбца.

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

Рассмотрим следующее - нормализованный набор данных ...

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id INT NOT NULL
,n INT NOT NULL
,val INT NOT NULL
,PRIMARY KEY(id,n)
);

INSERT INTO my_table VALUES
(1, 1, 3),
(1, 2, 2),
(1, 3, 1),
(2, 1, 6),
(2, 2, 5),
(2, 3, 7),
(3, 1, 2),
(3, 2, 3),
(3, 3, 1),
(4, 1, 1),
(4, 2, 6),
(4, 3, 5),
(5, 1, 5),
(5, 2, 6),
(5, 3, 7),
(6, 1, 3),
(6, 2, 5),
(6, 3, 6);

Вот быстрое (на запись) и грязное решение.Доступны более быстрые и элегантные решения ...

SELECT vals
     , COUNT(*) total
  FROM 
     ( SELECT id
            , GROUP_CONCAT(val ORDER BY val) vals 
         FROM my_table 
        GROUP 
           BY id
     ) x 
 GROUP 
    BY vals;
+-------+-------+
| vals  | total |
+-------+-------+
| 1,2,3 |     2 |
| 1,5,6 |     1 |
| 3,5,6 |     1 |
| 5,6,7 |     2 |
+-------+-------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...