показывая все повторяющиеся максимальные значения для каждого уникального идентификатора - PullRequest
0 голосов
/ 02 марта 2019

У меня есть таблицы данных, которые выглядят так:

table1:

 name | t2id  | percentage
-------------------------
  A   |  1    |    75
  B   |  1    |    75
  C   |  1    |    50
  D   |  2    |    30
  E   |  2    |    45
  F   |  2    |    45
  G   |  3    |    80
  H   |  3    |    70
  E   |  3    |    60

table2:

id  | name
-----------
 1  | NAME1
 2  | NAME2
 3  | NAME3

Я получил максимальный процент за каждый t2id сследующее:

SELECT t1.name, t2.name, MAX(t1.percentage) AS MAX_p 
FROM table1 t1 INNER JOIN table2 t2 ON t1.t2id = t2.id GROUP BY t1.t2id;

Вывод:

t1.name | t2.name | MAX_p
--------------------------
   A    |  NAME1  |  75
   E    |  NAME2  |  45
   G    |  NAME3  |  80

Теперь я также пытаюсь показать повторяющиеся максимальные значения для каждого t2id, что-то вроде этого:

t1.name | t2.name | MAX_p
--------------------------
   A    |  NAME1  |  75
   B    |  NAME1  |  75
   E    |  NAME2  |  45
   F    |  NAME2  |  45
   G    |  NAME3  |  80

Кажется, я не могу найти решение этой проблемы, я пытался с подзапросами, но не могу получить правильный вывод.Если бы кто-то мог помочь мне с тем, как я поступил бы, я был бы очень признателен

Ответы [ 3 ]

0 голосов
/ 02 марта 2019

Это стандартный SQL и будет работать со всеми версиями MySQL (и других СУБД)

SELECT t1.name AS t1name, t2.name AS t2name, t1.percentage
FROM table1 t1 
INNER JOIN table2 t2 ON t1.t2id = t2.id 
INNER JOIN 
    (SELECT t2id, MAX(percentage) AS MAX_p 
     FROM table1 t1
     GROUP BY t2id) m
  ON t1.t2id = m.t2id AND t1.percentage=m.MAX_p
0 голосов
/ 02 марта 2019

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

SELECT t1.name, t2.name, t1.percentage AS MAX_p 
FROM table1 t1 INNER JOIN
     table2 t2
     ON t1.t2id = t2.id
WHERE t1.percentage = (SELECT MAX(tt1.percentage)
                       FROM table1 tt1
                       WHERE tt1.t2id = t1.t2id
                      );

Преимущество этого подхода заключается в производительности - он не выполняет агрегирование всех данных.Фактически, с индексом на table1(t2id, percentage) предложение WHERE должно быть быстрым поиском в таблице.

Это может быть даже быстрее написано так:

SELECT t1.name,
       (SELECT t2.name FROM table2 t2 WHERE t1.t2id = t2.id) as t2_name,
       t1.percentage AS MAX_p 
FROM table1 t1
WHERE t1.percentage = (SELECT MAX(tt1.percentage)
                       FROM table1 tt1
                       WHERE tt1.t2id = t1.t2id
                      );

Это требуетindex on table2(id, name.

По сути, это должно быть сканирование table1 с быстрым поиском индекса в каждой строке для фильтрации.А затем дополнительный поиск по индексу table2, чтобы получить имя.

0 голосов
/ 02 марта 2019

Если вы используете MySQL 8 или более позднюю версию, то здесь можно использовать RANK:

WITH cte AS (
    SELECT t1.name, t2.name AS t2name, t1.percentage,
        RANK() OVER (PARTITION BY t2.id ORDER BY t1.percentage DESC) rnk
    FROM table1 t1
    INNER JOIN table2 t2
        ON t1.t2id = t2.id
)

SELECT name, t2name, percentage
FROM cte
WHERE rnk = 1;

Если вам нужна версия, которая будет работать на версиях MySQL ранее, чем 8, то мы должны сделатьбольше работы:

SELECT t1.name, t2.name, t1.percentage
FROM table1 t1
INNER JOIN table2 t2
    ON t1.t2id = t2.id
INNER JOIN
(
    SELECT t2.id, MAX(t1.percentage) AS max_percentage
    FROM table1 t1
    INNER JOIN table2 t2
        ON t1.t2id = t2.id
    GROUP BY t2.id
) t3
    ON t2.id = t3.id AND t1.percentage = t3.max_percentage;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...