适合where子句的组中的最大值

时间:2015-01-23 07:03:51

标签: mysql sql greatest-n-per-group

是的,这是另一个最好的每组问题!我已经尝试了几天试图解决这个问题但无济于事。我也一直在搜索,但我甚至不知道我是否在寻找合适的地方。问题的最简化版本如下:

我有2个表,一个是多对多的,另一个有数据。

--------a-------    ------------b-----------
| id | version |    | id  | version | external_ref |
|  1 |    1    |    |  1  |    1    |       9      |
|  1 |    2    |    |  1  |    2    |       8      |
|  1 |    3    |    |  1  |    3    |       7      |
|  2 |    1    |    |  2  |    1    |       5      |
|  2 |    2    |    |  2  |    2    |       6      |
       .                          .
       .                          .
       .                          .

这是我当前(显着简化的)查询以获得结果:

SELECT * FROM a 
    INNER JOIN (
        SELECT MAX(Version) FROM a GROUP BY id
    ) j ON a.id = j.id AND a.version = j.version
    LEFT JOIN b ON a.id = b.id AND a.version = b.version
WHERE  (b.external_ref = 9 
    OR b.external_ref = 8 (ect)
 ) AND (a.id = 1 OR
       a.id = 2)

此查询的问题是,如果external_ref = 7不在where子句中,则不返回任何行。

如果我查看只有external_ref 8,9或5的条目,那么我希望能够得到以下结果

| id | version |   data from table a    |
|  1 |    2    | some data from table a |
|  2 |    1    |   some more data       |

那么如何获得符合where子句的MAX(version)

完整查询是:

SELECT DISTINCT `t`.`Version`, `t`.`TermID`, `t`.`Definition`, `t`.`Name` 
FROM `term` AS `t`
  INNER JOIN (
    SELECT MAX(`Version`) version, `TermID`
    FROM `term`
    GROUP BY `termID`
) jj ON `t`.`TermID` = jj.`TermID` AND `t`.`Version` = jj.`Version`
LEFT JOIN `syllabusin` AS `si` ON `t`.`TermID` = `si`.`TermID` AND `t`.`Version` = `si`.`Version`
LEFT JOIN `synonyms` AS `sy` ON `t`.`TermID` = `sy`.`TermID`
WHERE
  (`si`.`SyllabusID` = 7  
   OR  `si`.`SyllabusID` = 6  
   OR  `si`.`SyllabusID` = 5  
   OR  `si`.`SyllabusID` = 4  
   OR  `si`.`SyllabusID` = 3  
   OR  `si`.`SyllabusID` = 2  
   OR  `si`.`SyllabusID` = 1  
   OR  `si`.`SyllabusID` = 8 )
AND (  `t`.`Name` LIKE '%term%'  
     OR  `t`.`Acronym` LIKE '%term%'  
     OR  `t`.`Definition` LIKE '%term%'  
     OR  `sy`.`Synonym` LIKE '%term%'  )    

修改

为了澄清我想要的内容,我希望从表a获取外部引用的行(external_ref = x),这些行具有其id的最大版本。

1 个答案:

答案 0 :(得分:2)

我认为这可能是它:

SELECT a.*
FROM a
JOIN (
    SELECT a.id, MAX(a.version) AS maxversion
    FROM a
    JOIN b ON a.id = b.id and a.version = b.version
    WHERE b.external_ref IN (9, 8)
    GROUP BY a.id
) AS amax ON a.id = amax.id AND a.version = amax.version

它也可以写成:

SELECT a.*
FROM a
JOIN (
    SELECT a.id, MAX(a.version) AS maxversion
    FROM a
    JOIN (SELECT *
          FROM b
          WHERE external_ref IN (9, 8)) AS b
    ON a.id = b.id and a.version = b.version
    GROUP BY a.id
) AS amax ON a.id = amax.id AND a.version = amax.version

对于更完整的查询,我认为您只需将所有连接和条件移动到子查询中:

SELECT DISTINCT `t`.`Version`, `t`.`TermID`, `t`.`Definition`, `t`.`Name` 
FROM `term` AS `t`
INNER JOIN (
    SELECT MAX(`Version`) version, `TermID`
    FROM `term` AS t
    JOIN syllabusin AS si ON `t`.`TermID` = jj.`TermID` AND `t`.`Version` = jj.`Version`
    JOIN `synonyms` AS `sy` ON `t`.`TermID` = `sy`.`TermID`
    WHERE
      (`si`.`SyllabusID` IN (7, 6, 5, 4, 3, 2, 1, 8)
    AND (  `t`.`Name` LIKE '%term%'  
         OR  `t`.`Acronym` LIKE '%term%'  
         OR  `t`.`Definition` LIKE '%term%'  
         OR  `sy`.`Synonym` LIKE '%term%'  )        
    GROUP BY `termID`
) jj ON `t`.`TermID` = jj.`TermID` AND `t`.`Version` = jj.`Version`

它与早期查询的逻辑基本相同:您执行具有所有条件的连接,并从中获取每个ID的最大版本。然后加入原始表,只选择与ID和最大版本匹配的行。