从MySQL数据库中的多个相同行中选择最新记录

时间:2016-07-20 17:44:33

标签: mysql unique distinct

我正在开发一个产品样本库存系统,用于跟踪产品的移动。每种产品的状态可以具有“IN”或“OUT”或“REMOVED”状态。表的每一行代表一个新条目,其中ID,状态和日期是唯一的。每个产品还有一个序列号。

我需要有关SQL查询的帮助,该查询将返回当前“OUT”的所有产品。如果我只是选择SELECT * FROM table WHERE status = "IN",它将返回所有状态为IN的产品。

每次产品进出时,我都会复制该特定产品的最后一行并更改状态并更新日期,它会自动获得新ID。

这是我的表格:

id | serial_number  | product | color  | date       | status
------------------------------------------------------------
 1 | K0T4N          | XYZ     | silver | 2016-07-01 | IN
 2 | X56Z7          | ABC     | silver | 2016-07-01 | IN
 3 | 96T4F          | PQR     | silver | 2016-07-01 | IN
 4 | K0T4N          | XYZ     | silver | 2016-07-02 | OUT
 5 | 96T4F          | PQR     | silver | 2016-07-03 | OUT
 6 | F0P22          | DEF     | silver | 2016-07-04 | OUT
 7 | X56Z7          | ABC     | silver | 2016-07-05 | OUT
 8 | F0P22          | DEF     | silver | 2016-07-06 | IN
 9 | K0T4N          | XYZ     | silver | 2016-07-07 | IN
10 | X56Z7          | ABC     | silver | 2016-07-08 | IN
11 | X56Z7          | ABC     | silver | 2016-07-09 | REMOVED
12 | K0T4N          | XYZ     | silver | 2016-07-10 | OUT
13 | 96T4F          | PQR     | silver | 2016-07-11 | IN
14 | F0P22          | DEF     | silver | 2016-07-12 | OUT

2 个答案:

答案 0 :(得分:1)

此查询将为您提供每个serial_number

的所有最新记录
SELECT a.* FROM your_table a
LEFT JOIN your_table b ON a.serial_number = b.serial_number AND a.id < b.id
WHERE b.serial_number IS NULL

以下查询将给出您的预期结果

SELECT a.* FROM your_table a
LEFT JOIN your_table b ON a.serial_number = b.serial_number AND a.id < b.id
WHERE b.serial_number IS NULL AND a.status LIKE 'OUT'

答案 1 :(得分:1)

有两种很好的方法可以做到这一点。在性能方面,哪种方式最好可能取决于各种因素,因此请尝试两者。

SELECT
t1.*
FROM table t
LEFT OUTER JOIN table later_t
ON later_t.serial_number = t.serial_number
AND later_t.date > t.date
WHERE later_t.id IS NULL
AND t.status = "OUT"

您从later_t检查IS NULL的哪一列无关紧要,只要该列在表定义中声明为NOT NULL

另一种逻辑等效的方法是:

SELECT
t.*
FROM table t
INNER JOIN (
SELECT
serial_number,
MAX(date) AS date
FROM table
GROUP BY serial_number
) latest_t
ON later_t.serial_number = t.serial_number
AND latest_t.date = t.date
WHERE t.status = "OUT"

对于每个查询,我强烈建议使用以下索引:

ALTER TABLE table
ADD INDEX `LatestSerialStatus` (serial_number,date)

我在自己的工作中经常使用这种类型的查询,并将上述索引作为表的主键。在这种情况下,对于这些类型的查询,查询性能非常快。

另请参阅此查询类型的documentation