选择多列的max()

Scu*_*Kay 13 mysql sql

好的,这是我的桌子:

product_id  version_id  update_id  patch_id
  1           1           0          0
  1           1           1          0
  1           1           1          1
  1           1           2          0
  1           1           2          1
  2           1           0          0
  2           2           0          0
  2           3           0          0
  2           3           0          1
  3           1           0          0
  3           1           0          1
Run Code Online (Sandbox Code Playgroud)

现在我想选择产品的最新版本,因此具有最高update_id和patch_id的版本.

例如,最新版本的

  • 产品1应返回1,2,1
  • 产品2应该返回3,0,1
  • 产品3应返回1,0,1

我正在尝试使用GROUP BY和HAVING的各种东西,尝试了子查询,但我仍然无法找到实现这一目标的方法.

任何人都可以帮我找到正确的查询,还是应该考虑为此编写一个php函数?

编辑

一些额外的信息: - 列一起是主键(有更多列,但对于这个问题,它们无关紧要) - 没有列是自动增量

这是表:

CREATE  TABLE IF NOT EXISTS `db`.`patch` (
`product_id` INT NOT NULL ,
`version_id` INT NOT NULL ,
`update_id` INT NOT NULL ,
`patch_id` INT NOT NULL
PRIMARY KEY (`product_id`, `version_id`, `update_id`, `patch_id`) ,
INDEX `fk_patch_update1` (`product_id` ASC, `version_id` ASC, `update_id` ASC) )
Run Code Online (Sandbox Code Playgroud)

编辑2

标记为重复,但不是:另一个问题查找的记录高于三个不同列中任何一列的值.

在这个问题中,我们寻找由product_id分组的最高版本号.

编辑3

rgz的回答再次告诉我,这是重复的.首先:这个问题比较老了.其次,我不认为答案是一样的.

rgz建议使用以下查询:

SELECT product_id, GREATEST(version_id, update_id, patch_id) AS latest_version FROM patch.
Run Code Online (Sandbox Code Playgroud)

GREATEST(1,2,3)返回3,对吗?Wat如果我们有这些值:

  product_id  version_id  update_id  patch_id
  1           1           0          0
  1           1           2          8
  1           3           0          0
Run Code Online (Sandbox Code Playgroud)

据我了解,此查询将返回:

  product_id  latest_version
  1                 1
  1                 8
  1                 3
Run Code Online (Sandbox Code Playgroud)

但它应该返回:

  product_id  version_id update_id  patch_id
  1           3          0          0
Run Code Online (Sandbox Code Playgroud)

我认为GREATEST不会有所帮助.如果你认为它会,请证明我错了.

Mat*_*lie 9

这是独特标识有用的一个例子.

想象一下,您有一个autoincrememnting ID字段,然后您可以使用相关的子查询找到每个产品所需的ID ...

SELECT
  *
FROM
  yourTable
WHERE
  id = (
        SELECT   id
        FROM     yourTable AS lookup
        WHERE    lookup.product_id = yourTable.product_id
        ORDER BY version_id DESC, update_id DESC, patch_id DESC
        LIMIT    1
       )
Run Code Online (Sandbox Code Playgroud)


没有唯一标识符的等价物需要多个相关的子查询...

SELECT
  *
FROM
  yourTable
WHERE
     version_id = (
                   SELECT   MAX(version_id)
                   FROM     yourTable AS lookup
                   WHERE    lookup.product_id = yourTable.product_id
                  )
  AND update_id = (
                   SELECT   MAX(update_id)
                   FROM     yourTable AS lookup
                   WHERE    lookup.product_id = yourTable.product_id
                     AND    lookup.version_id = yourTable.version_id
                  )
  AND patch_id  = (
                   SELECT   MAX(patch_id)
                   FROM     yourTable AS lookup
                   WHERE    lookup.product_id = yourTable.product_id
                     AND    lookup.version_id = yourTable.version_id
                     AND    lookup.update_id  = yourTable.update_id
                  )
Run Code Online (Sandbox Code Playgroud)

这将明显慢于具有唯一标识符列的表.


另一种替代方案(没有唯一标识符)是在不同的聚合级别上自我加入.

SELECT
  yourTable.*
FROM
  (SELECT product_id, MAX(version_id) AS max_version_id FROM yourTable GROUP BY product_id) AS version
INNER JOIN
  (SELECT product_id, version_id, MAX(update_id) AS max_update_id FROM yourTable GROUP BY product_id, version_id) AS update
    ON  update.product_id = version.product_id
    AND update.version_id = version.max_version_id
INNER JOIN
  (SELECT product_id, version_id, updatE_id, MAX(patch_id) AS max_patch_id FROM yourTable GROUP BY product_id, version_id) AS patch
    ON  patch.product_id = update.product_id
    AND patch.version_id = update.version_id
    AND patch.update_id  = update.max_update_id
INNER JOIN
  yourTable
    ON  yourTable.product_id = patch.product_id
    AND yourTable.version_id = patch.version_id
    AND yourTable.update_id  = patch.update_id
    AND yourTable.patch_id   = patch.max_patch_id
Run Code Online (Sandbox Code Playgroud)