Выберите максимальный номер версии для каждой группы, состоящей из нескольких столбцов

0

У меня есть следующие таблицы:

Программы

TYPE_ID | BUILD_ID | CONFIG_ID | VERSION_ID | (All foreign keys to the respective tables)
1       | 1        | 1         | 1          |
1       | 1        | 1         | 2          |
2       | 2        | 3         | 3          |
2       | 2        | 3         | 4          |

Версии

ID | major | minor | patch
1  | 1     |0      |1
2  | 2     |0      |0
3  | 3     |0      |3
4  | 4     |0      |0

Мне нужно выбрать строки с наивысшей версией из таблицы Apps для каждой уникальной комбинации TYPE_ID, BUILD_ID и CONFIG_ID.

Номер версии должен быть рассчитан MAX(major * 1000000 + minor * 1000 + patch) в таблице версий.

Таким образом, из приведенного примера таблицы Apps результат:

TYPE_ID | BUILD_ID | CONFIG_ID | VERSION_ID |
1       | 1        | 1         | 2          |
2       | 2        | 3         | 4          |

Попробовали что-то вроде этого:

SELECT p1.* FROM Apps p1 
            INNER JOIN ( 
                SELECT max(VERSION_ID) MaxVersion, CONFIG_ID 
                FROM Apps  
                GROUP BY CONFIG_ID
            ) p2 
            ON p1.CONFIG_ID = p2.CONFIG_ID 
                AND p1.VERSION_ID = p2.MaxVersion  
            GROUP BY 'TYPE_ID', 'BUILD_ID', 'CONFIG_ID'

Но MAX применяется на VERSION_ID и мне нужно, чтобы MAX применялся к major, minor и patch комбинациям.

Распространение MySQL версии 15.1 5.5.56-MariaDB

Любая помощь будет оценена по достоинству.

Ура!

  • 0
    Какую версию MySQL вы используете?
  • 0
    ваш ожидаемый результат имеет идентификатор версии (или номер версии?)
Показать ещё 3 комментария
Теги:
group-by
max

5 ответов

1
Лучший ответ

Вы можете вычислить максимальную версию для type_id, build_id, config_id используя формулу, описанную в вашем вопросе, использовать ее снова в той же формуле, чтобы найти версию:

SELECT sq.type_id, sq.build_id, sq.config_id, versions.id AS version_id_max
FROM (
    SELECT type_id, build_id, config_id, MAX(major * 1000000 + minor * 1000 + patch) AS max_version
    FROM apps
    INNER JOIN versions ON apps.version_id = versions.id
    GROUP BY type_id, build_id, config_id
) sq
INNER JOIN versions ON max_version = major * 1000000 + minor * 1000 + patch
+---------+----------+-----------+----------------+
| type_id | build_id | config_id | version_id_max |
+---------+----------+-----------+----------------+
|       1 |        1 |         1 |              2 |
|       2 |        2 |         3 |              4 |
+---------+----------+-----------+----------------+
  • 0
    Brillian @Salman A, это почти то, что мне нужно, но можно ли будет вернуть только оригинальный столбец VERSION_ID в конце вместо последних 5 столбцов? Ура!
  • 0
    @MariusKurgonas просто назовите столбцы (я использовал * чтобы показать все детали, включая ненужные).
Показать ещё 1 комментарий
1

Попробуй это:

select type_id, build_id, config_id,
      max(1000000*v.major+1000*v.minor+v.patch) as version 
from apps a left join versions v on a.version_id=v.id 
group by type_id, build_id, config_id
  • 0
    Ура! Но это не возвращает исходные строки таблицы Apps в конечных результатах, поэтому - не принял это как ответ ...
1

Использование вложенных производных подзапросов и немного хакерского способа идентификации VERSION_ID соответствующего MAX VERSION_NO.

Сначала мы получаем сначала производную таблицу, определяющую VERSION_NO для каждой строки таблицы Apps.

Теперь, используя эту производную таблицу в качестве источника для SELECT, мы группируем по TYPE_ID, BUILD_ID и CONFIG_ID и используем трюк GROUP_CONCAT и манипуляции с строкой, мы определяем VERSION_ID соответствующий максимальному VERSION_NO, для группы.

Попробуйте следующее:

SELECT nest.TYPE_ID, 
       nest.BUILD_ID, 
       nest.CONFIG_ID, 
       SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT nest.VERSION_ID   
                                    ORDER BY nest.VERSION_NO DESC  
                                    SEPARATOR ','), ',', 1) AS VERSION_ID 
FROM (
       SELECT A.TYPE_ID, 
              A.BUILD_ID, 
              A.CONFIG_ID, 
              A.VERSION_ID, 
              (V.major*1000000 + V.minor*1000 + V.patch) AS VERSION_NO 
       FROM Apps AS A
       INNER JOIN Versions AS V ON V.ID = A.VERSION_ID 
     ) AS nest 
GROUP BY nest.TYPE_ID, nest.BUILD_ID, nest.CONFIG_ID 

SQL FIDDLE

0

Попробуйте этот запрос, что я здесь делаю, я имитирую известную функцию ROW_NUMBER() OVER (PARTITION BY Type_id, Build_id, Config_id ORDER BY major desc, minor desc, patch desc).

select @type_id_lag := 0, @build_id_lag :=0, @config_id_lag := 0, @rn := 0;

select type_id, build_id, config_id, major, minor, patch from (
    select case when @type_id_lag = type_id and
                     @build_id_lag = build_id and
                     @config_id_lag = config_id then @rn := @rn + 1 else @rn := 1 rn,
           @type_id_lag := type_id type_id,
           @build_id_lag := build_id build_id,
           @config_id_lag := config_id config_id,
           v.major, v.minor, v.patch
    from Apps a
    left join Versions v on a.version_id = v.id
    order by a.type_id, a.build_id, a.config_id,
             v.major desc, v.minor desc, v.patch desc
) a where rn = 1;
0

Попробуй это:

SELECT a1.type_id, a1.build_id, a1.config_id, a1.version_id
FROM apps a1
WHERE NOT EXISTS(
    (SELECT 'NEXT'
    FROM apps a2
    WHERE a2.type_id = a1.type_id
    AND a2.build_id = a1.build_id
    AND a2.config_id = a1.config_id
    AND a2.version_id > a1.version_id))
  • 0
    Спасибо @Joe Taras, но похоже, что в этом примере сравниваются идентификаторы версий, а не реальные версии минорных патчей ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню