【问题标题】:Select max version number for each group consisting of multiple columns为由多列组成的每个组选择最大版本号
【发布时间】:2018-09-14 12:53:03
【问题描述】:

我有以下表格:

应用程序

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_IDBUILD_IDCONFIG_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 应用于majorminorpatch 组合。

MySQL 版本 15.1 分发版 5.5.56-MariaDB

任何帮助将不胜感激。

干杯!

【问题讨论】:

  • 你使用的是什么 MySQL 版本?
  • 您的预期结果有版本 id(或者,版本号?)
  • max(x * y * x ...) 解决问题了吗?
  • @Mureinik 查看编辑。
  • @MariusKurgonas 请检查stackoverflow.com/a/52332488/2469308

标签: mysql sql group-by max


【解决方案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 |
+---------+----------+-----------+----------------+

【讨论】:

  • Brillian @Salman A,这几乎是我所需要的,但是否可以在末尾返回原始的 VERSION_ID 列而不是最后 5 列?干杯!
  • @MariusKurgonas 只是命名列(我使用* 显示所有细节,包括不必要的细节)。
  • 干杯!这就是我需要的 - 但使用 Apps 表列的原始名称。因此,如果我将 version_id_max 重命名为 version_id 就可以了!
【解决方案2】:

试试这个:

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

【讨论】:

  • 干杯!但这不会在最终结果中返回原始的 Apps 表行 - 不接受这个作为答案......
【解决方案3】:

利用嵌套的派生子查询,以及标识VERSION_IDbit of hacky way 对应于MAX VERSION_NO

我们基本上首先得到一个派生表,确定Apps 表中每一行的VERSION_NO

现在使用该派生表作为SELECT 的源,我们按TYPE_IDBUILD_IDCONFIG_ID 分组,并使用GROUP_CONCAT 和基于字符串操作的技巧,我们确定@987654332 @ 对应于最大 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

【讨论】:

    【解决方案4】:

    试试这个:

    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))
    

    【讨论】:

    • 感谢@Joe Taras,但似乎这个示例比较的是版本 ID,而不是实际的主要次要补丁版本...
    【解决方案5】:

    试试这个查询,我这里做什么,我模仿知名函数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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 2012-01-04
      • 2014-05-12
      • 1970-01-01
      相关资源
      最近更新 更多