MySQL存储和查询最新的软件版本

时间:2016-07-13 22:23:01

标签: mysql sql

使用以下示例表,我想创建一个MySQL查询,该查询返回以下每个虚构应用程序的最新版本(基于传统的软件版本编号)。我使用的是MySQL版本5.5.17。

如果可以创建一个能够提供更优雅查询的函数,我还会考虑使用存储函数。

app   | major | minor | patch  
------+-------+-------+--------
cat   | 2     | 15    | 0      
cat   | 2     | 15    | 1      
cat   | 2     | 2     | 0      
dog   | 1     | 0     | 1      
dog   | 1     | 7     | 2      
dog   | 3     | 0     | 0      
fish  | 2     | 2     | 5      
fish  | 2     | 3     | 1      
fish  | 2     | 11    | 0       

预期查询结果:

app   | major | minor | patch  
------+-------+-------+--------
cat   | 2     | 15    | 1      
dog   | 3     | 0     | 0      
fish  | 2     | 11    | 0     

您可以使用此sql创建名为my_table的表,以便进行测试。

CREATE TABLE IF NOT EXISTS `my_table` (
  `app` varchar(10) NOT NULL,
  `major` int(11) NOT NULL DEFAULT '0',
  `minor` int(11) NOT NULL DEFAULT '0',
  `patch` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `my_table` (`app`, `major`, `minor`, `patch`) VALUES
    ('cat', 2, 15, 1),
    ('cat', 2, 15, 0),
    ('cat', 2, 2, 0),
    ('dog', 1, 0, 1),
    ('dog', 1, 7, 2),
    ('dog', 3, 0, 0),
    ('fish', 2, 2, 5),
    ('fish', 2, 3, 1),
    ('fish', 2, 11, 0);

2 个答案:

答案 0 :(得分:2)

如果您认为次要版本和补丁永远不会超过1000,则可以将它们合并为一个数字major*100000 + minor*1000 + patch。然后,您可以在为每行计算后,在SQL Select only rows with Max Value on a Column处应用其中一种技术。

SELECT m.*
FROM my_table AS m
JOIN (SELECT app, MAX(major*1000000 + minor*1000 + patch) AS maxversion
      FROM my_table
      GROUP BY app) AS m1
ON m.app = m1.app AND major*1000000 + minor*1000 + patch = maxversion

DEMO

答案 1 :(得分:0)

我能想到三种方法。并且所有这些都非常难看,并且所有这些都涉及子查询.... 1)在GROUP BY查询的SELECT列表中使用相关子查询,2)使用内联视图来获得(零填充)major_minor_patch的规范字符串连接的最大值0002_0015_0001,然后解压缩字符串表示,或者连接到表以获取匹配的行,或者3)使用按app排序行的查询,然后按每个应用程序的最高版本排序,以及使用用户定义值的技巧(不支持)标记"第一"每个应用程序的行。这些都不是很好。

这是一种方法的演示。

我们从这开始,获取每个应用程序:

SELECT t.app
  FROM my_table t
 GROUP BY t.app

下一步,获得最高的" major"对于每个应用程序,我们可以这样做:

SELECT t.app
     , MAX(t.major) AS major
  FROM my_table t
 GROUP BY t.app

要获得该专业中的最高未成年人,我们可以将其设为内联视图...将其包装在parens中并像其他查询中的表一样引用它

SELECT t2.app
     , t2.major
     , MAX(t2.minor) AS minor
  FROM my_table t2
  JOIN ( 
         SELECT t.app
              , MAX(t.major) AS major
           FROM my_table t
          GROUP BY t.app
       ) t1
    ON t2.app   = t1.app
   AND t2.major = t1.major
 GROUP BY t2.app, t2.major

要获得最高的补丁,我们遵循相同的模式。将以前的查询用作内联视图。

SELECT t4.app
     , t4.major
     , t4.minor
     , MAX(t4.patch) AS patch
  FROM my_table t4
  JOIN ( -- query from above goes here
         SELECT t2.app
              , t2.major
              , MAX(t2.minor) AS minor
           FROM my_table t2
           JOIN ( SELECT t.app
                       , MAX(t.major) AS major
                    FROM my_table t
                   GROUP BY t.app
                ) t1
             ON t2.app   = t1.app
            AND t2.major = t1.major
          GROUP BY t2.app, t2.major 
       ) t3
    ON t4.app   = t3.app
   AND t4.major = t3.major
   AND t4.minor = t3.minor
GROUP BY t4.app, t4.major, t4.minor

这只是一种方法的一个例子。

随访:

对于另一种方法(获得版本的规范表示,即将#34; major"," minor"" patch"的值组合在一起单个表达式,以便结果可以通过该表达式排序"以获得最高版本),请参阅Gordon的答案。