根据最新快照检索给定类别的产品列表?

时间:2015-06-17 11:01:07

标签: mysql sql

我有一份产品清单和一份类别清单 每个产品在特定时间内属于某些类别,
即,我们不时更换产品类别。

因此,为了保留日志,我有一个包含3个字段的表Product_Category

category_id [INT], product_id [INT], snapshot_date [DATE]

snapshot_date是包含其所有产品的类别的最后更新时间

我想为给定的category_id(假设为category_id = 1)选择所有产品ID,其中我只想要此类别的最后一个快照的产品

例如假设Product_Category中的数据:

+-------------+------------+---------------+
| category_id | product_id | snapshot_date |
+-------------+------------+---------------+
|      1      |      1     |   2015-01-01  |  -----> old snapshot ignore it
|      1      |      2     |   2015-01-01  |  -----> old snapshot ignore it
|      1      |      3     |   2015-01-01  |  -----> old snapshot ignore it
|      1      |      1     |   2015-01-07  |  -----> last snapshot for category 1, this is my target
|      1      |      5     |   2015-01-07  |  -----> last snapshot for category 1, this is my target
|      1      |      7     |   2015-01-07  |  -----> last snapshot for category 1, this is my target
|      2      |      5     |   2015-01-01  |  -----> another category, old snapshot, ignore it
|      2      |      7     |   2015-01-07  |  -----> another category, last snapshot, ignore it
|      2      |      3     |   2015-01-07  |  -----> another category, last snapshot, ignore it
+-------------+------------+---------------+

鉴于category_id = 1,我希望结果为

+------------+
| product_id |
+------------+
|      1     |
|      5     |
|      7     |
+------------+

这是我到目前为止所做的事情:

SELECT product_id
FROM Product_Category
WHERE category_id = 1
      AND snapshot_date = (
          SELECT MAX( snapshot_date )
          FROM Product_Category
          WHERE category_id = 1
      );

进行嵌套选择是否有更好的解决方案?
PS,如果基于RDBMS的答案可能有所不同,我正在使用MySQL

1 个答案:

答案 0 :(得分:1)

您的查询应该没问题。但是,某些版本的MySQL可能会为外部查询中处理的每一行运行子查询。解决方案是将子查询移动到FROM子句:

SELECT pc.product_id
FROM Product_Category pc JOIN
     (SELECT category_id, MAX( snapshot_date ) as maxsd
      FROM Product_Category
      WHERE category_id = 1
      GROUP BY category_id
     ) pcmax
     ON pc.category_id = pcmax.category_id and
        pc.snapshot_date = pcmax.stampshot_date;

大多数数据库(包括我相信最新版本的MySQL)只会在查询中执行一次子查询。但是,此结构可确保子查询仅执行一次。