2012-03-14 50 views
0

說我有一張3列的表格:version_id,name,value發現版本ID中名稱/值對之間的差異

從概念上講,這個表格有一堆名稱 - 值對,每個version_id

如何編寫一個查詢,該查詢僅顯示名稱值對在版本-ID中不相同的前兩個version_ids的名稱值對?

此外,我想知道是否有一種方法可以將不同的名稱 - 值對並排放置在不同的version_ids中,也可以讓結果中的行彼此相鄰。

基本上,我想要比較兩個版本的差異。

例子:

version_id name   value 
    23459 jsLibrary2  JQuery_1_4_3 
    23459 jsLibrary1  CrossDomainAjax_1_0 
    23456 jsLibrary2  JQuery_1_4_2 
    23456 jsLibrary1  CrossDomainAjax_1_0 
    23456 groovyInclude2 GroovyUtilities 
    23454 jsLibrary2  JQuery_1_4_2 
    23454 jsLibrary1  CrossDomainAjax_1_0 
    23454 groovyInclude2 GroovyUtilities 

理想的查詢結果:

23456 jsLibrary2  JQuery_1_4_2 
23459 jsLibrary2  JQuery_1_4_3 
23456 groovyInclude2 GroovyUtilities 
23459 NULL   NULL 

注意,最好將注意新的名稱 - 值對(其中名稱不小VERSION_ID存在)和刪除名稱 - 值對(其中名稱不存在於較大的version_id中)

+0

你能舉一個小例子嗎? – 2012-03-14 01:36:13

+0

我添加了一個例子。 – Muhd 2012-03-14 01:49:48

+0

你試過了:select table_id,name,value from tablename group by concat(name,「」,value) – 2012-03-14 02:03:27

回答

0

我敢肯定,這可以簡化—或者至少,我真的希望它能—但:

SELECT name, 
     version_id_before, 
     (SELECT value 
      FROM property_history 
      WHERE name = t.name 
      AND version_id = version_id_before 
     ) AS value_before, 
     (SELECT MIN(version_id) 
      FROM property_history 
      WHERE version_id > version_id_before 
     ) AS version_id_after, 
     (SELECT value 
      FROM property_history 
      WHERE name = t.name 
      AND version_id = 
       (SELECT MIN(version_id) 
        FROM property_history 
        WHERE version_id > version_id_before 
       ) 
     ) AS value_after 
    FROM (SELECT name, 
       CASE WHEN EXISTS 
          (SELECT 1 
           FROM property_history 
           WHERE name = ph1.name 
           AND version_id = 
            (SELECT MAX(version_id) 
             FROM property_history 
            ) 
          ) 
        THEN (SELECT MAX(version_id) 
           FROM property_history ph2 
          WHERE NOT EXISTS 
             (SELECT 1 
              FROM property_history 
              WHERE name = ph1.name 
              AND version_id = ph2.version_id 
              AND value = 
                (SELECT value 
                 FROM property_history 
                WHERE name = ph1.name 
                 AND version_id = 
                  (SELECT MAX(version_id) 
                   FROM property_history 
                  ) 
               ) 
             ) 
         ) 
        ELSE (SELECT MAX(version_id) 
           FROM property_history 
          WHERE name = ph1.name 
         ) 
       END AS version_id_before 
      FROM property_history ph1 
      GROUP 
      BY name 
     ) AS t 
WHERE version_id_before IS NOT NULL 
; 

(免責聲明:僅使用您的示例數據集進行測試,爲此給出結果:

+----------------+-------------------+-----------------+------------------+--------------+ 
| name   | version_id_before | value_before | version_id_after | value_after | 
+----------------+-------------------+-----------------+------------------+--------------+ 
| groovyInclude2 |    23456 | GroovyUtilities |   23459 | NULL   | 
| jsLibrary2  |    23456 | JQuery_1_4_2 |   23459 | JQuery_1_4_3 | 
+----------------+-------------------+-----------------+------------------+--------------+ 

我還沒有做任何努力來構建其他數據集來測試它。)

0

我認爲您需要使用幾個子查詢才能獲得所需的結果,因爲您正在查找r第一和第二個值。我假設這個名字是「關鍵」,你必須小組,在這種情況下的東西沿着這些路線應該工作:

Select 
    firstVersion.firstVersionId, 
    firstVersionDetails.name as firstVersionName, 
    firstVersionDetails.value as firstVersionValue, 
    --second version values will be null if there is no second value 
    secondVersion.secondVersionId, 
    secondVersionDetails.name as secondVersionName, --always the same as firstVersionName because name is a key field 
    secondVersionDetails.value as secondVersionValue 
From 
    ( 
      Select 
       name, 
       Max(version_id) as firstVersionId 
      From versions 
      Group by name 
    ) as firstVersion 
    join versions as firstVersionDetails--inner join because every name has a first version 
      on firstVersions.version_id = firstVersion.firstVersionId 
    left outer Join --outer join so we always get the first version and get the second version whenever there is one (in other words, does *not* limit data to names with at least 2 versions) 
    (
      select 
       name, 
       Max(version_id) as secondVersionId 
      from versions 
      Group by name 
    ) as secondVersion 
     on firstVersion.name=secondVersion.name 
     and secondVersion.version_id < firstVersion.firstVersionId --exclude the first version when calculating the 'max'. This is the part of the join that allows us to identify the second version 
    left outer join versions as secondVersionDetails --using outer join again so we don't limit our data to names with 2 versions 
      on secondVersion.secondVersionId = secondVersionDetails.version_id 

快樂查詢! :-)

0

如何對這種做法 -

SELECT MAX(version_id) INTO @cur FROM tbl; 
SELECT MAX(version_id) INTO @prev FROM tbl WHERE version_id < @cur; 

SELECT name, @prev, MAX(IF(version_id = @prev, value, '')) AS prev_val, @cur, MAX(IF(version_id = @cur, value, '')) AS cur_val 
FROM tbl 
WHERE version_id IN (@prev, @cur) 
GROUP BY name 
HAVING cur_val <> prev_val; 
相關問題