2016-07-13 1 views
0

次のサンプルテーブルを使用して、従来のソフトウェアバージョン番号に基づいて、次の各仮想アプリケーションの最新バージョンを返すMySQLクエリを作成します。私はMySQLバージョン5.5.17を使用しています。MySQLが最新のソフトウェアバージョンを保存してクエリする

より洗練されたクエリを作成できる関数を作成できる場合は、ストアド関数の使用も検討します。

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  

あなたがテストできるようにするには、MY_TABLEという名前のテーブルを作成するには、このSQLを使用することができます。

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); 
+0

私は考えることができる3つのアプローチがあります。そしてそれらのすべてはかなり醜いです、そして、それらのすべてがサブクエリを含んでいます....1)GROUP BY問合せのSELECTリストで相関サブクエリを使用する2)インライン・ビューを使用して(ゼロ埋め込み)major_minor_patch 0002_0015_0001のカノニカル文字列連結の最大値を取得し、文字列表現を解凍するか、または表に結合して一致する行を取得する、または3)各アプリの行を並べ替えるクエリを使用し、次に各アプリの最高バージョンで、ユーザー定義の値を持つトリック(サポートされていない)を使用して、各アプリの「最初の」行にフラグを立てます。それらのどれもかなりです。 – spencer7593

+1

http://sqlfiddle.com/#!9/bd378/3 – Strawberry

+0

テーブルを変更して別の列を追加するオプションがありますか? – Mjh

答えて

2

マイナーバージョンとパッチが決して1000を超えないと仮定すると、それらを単一の数字major*100000 + minor*1000 + patchに組み合わせることができます。次に、各行についてこれを計算した後、SQL Select only rows with Max Value on a Columnに技術の1つを適用することができます。

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

+0

これは最も簡潔なアプローチです。+ 10。私は文字列表現を使用して正準表現を得るという点でこのアプローチを考えていました。 'CONCAT(メジャー、10、 '0')、LPAD(マイナー、10、 '0')、LPAD(パッチ、10,0))' – spencer7593

+0

文字を含むバージョニングスキームを使用すると、それを行う方法。 – Barmar

+0

INET_ATONもかなりの範囲の値で動作しますが、厳密には 'ハック' – Strawberry

0

私は考えることができる3つのアプローチがあります。これらのすべてはサブクエリを含んでいます.... 1)GROUP BYクエリのSELECTリストで相関サブクエリを使用する、2)インラインビューを使用して(ゼロ埋め込み)major_minor_patchの正規文字列連結の最大値を取得する0002_0015_0001を使用して文字列表現を解凍するか、テーブルに結合して一致する行を取得するか、または3)アプリごとに行を並べ替えるクエリを使用し、次に各アプリの最高バージョンとユーザー定義の値でトリック(サポートされない)各アプリの「最初の」行にフラグを立てます。これらのどれもきれいです。


ここでは、1つのアプローチのデモです。

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

次のステップは、我々はこのような何かを行うことができ、それぞれのアプリのために最高の「主要」を取得:

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

取得するには

は、私たちは、それぞれのアプリを取得し、これを起動しますそのメジャー内の最高のマイナーなものをインラインビューにすることができます。それを括弧で囲み、別のクエリのテーブルのように参照します。

最高のパッチを得るために、我々は同じパターンに従っています。前のクエリをインラインビューとして使用する。

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 

これは単なる1つのアプローチの例です。


フォロー:バージョンの正規表現を取得する別のアプローチを

(即ち、単一の式で、「メジャー」、「マイナー」および「パッチ」の値を結合するように結果は、その式によって最も高いバージョンを得るために "順序付けられる"ことができる)、ゴードンからの答えを見てください。

関連する問題