MySQL在接受条件下查找最近更新的项目

时间:2015-03-27 12:37:32

标签: mysql

我有一个包含以下列的表:

  • id
  • id_number
  • description
  • register_date
  • 接受

id_number不是唯一的,因为我可以在同一个表上有多个元素。我需要使用以下标准找到每个id_number中的一个元素:

  • 如果该项目已被接受至少一次,我需要使用较新的register_date的项目,但只查看同类项目。
  • 如果该项目尚未被接受,那么我需要已注册的最新项目。

例如,如果我有以下数据:

ID Id_Number    Description             Register_Date         Accepted
==============================================================================
1  TA-001       This is a test           19/02/2015 15:40:35      0
2  TA-004       test                     27/03/2015 12:00:18      1
3  DCMIX-001    test                     01/01/2011 00:00:00      0
4  TA-005       test                     01/01/2010 00:00:00      0
5  TA-001       different description    25/03/2015 11:07:42      1
6  TA-001       not accepted but newer   25/03/2015 11:53:42      0
7  TA-005       test                     27/03/2015 13:10:21      0

将产生这个ouptut:

ID Id_Number    Description             Register_Date         Accepted
==============================================================================   
2  TA-004       test                    27/03/2015 12:00:18       1
3  DCMIX-001    test                    01/01/2011 00:00:00       0    
5  TA-001       different description   25/03/2015 11:07:42       1
7  TA-005       test                    27/03/2015 13:10:21       0

非常感谢你的时间。

2 个答案:

答案 0 :(得分:1)

如果该项目至少被接受过一次,我需要使用较新的register_date的项目,但只查看同类项目。

SELECT *
FROM (SELECT id_number,MAX(register_date) FROM mytable WHERE accepted = 1 GROUP BY id_number) accepted
JOIN mytable ON (mytable.id_number = accepted.id_number AND mytable.register_date = accepted.register_date)

如果该项目尚未被接受,那么我需要已注册的最新项目。

SELECT *
FROM
(
    SELECT id_number
    FROM mytable
    GROUP BY id_number
    HAVING SUM(accepted) = 0
) not_accepted
LEFT JOIN mytable ON (mytable.id_number = not_accepted.id_number)
GROUP BY mytable.id_number
ORDER BY register_date DESC

答案 1 :(得分:1)

尝试此查询:

SELECT l.*
FROM mytable l                         # 'l' from 'last'
LEFT JOIN mytable n                    # 'n' from 'newer'
    ON l.id_number = n.id_number       # match by in_number
    AND (l.accepted < n.accepted OR    # 'l' < 'n' on (accepted, register_date)
         l.accepted = n.accepted AND l.register_date < n.register_date)
WHERE n.id_number IS NULL              # 'n' (newer) does not exist

它会在单个查询中选择您需要的所有行,并且比使用GROUP BY的查询运行得更快。

如何运作

LEFT JOIN将左表中的所有行(来自l的别名为last)与右表中的匹配行组合在一起(别名为n来自{ {1}})。表newer中的每一行都与表l中具有相同n的所有行配对,并且还存在id_number字段对的条件。

您的请求是为每个(accepted, register_date)选择具有最新(最大)id_number的行,register_date的行优先于accepted = 1的行。这意味着,对于accepted = 0的每个值,请在字典顺序中选择具有对id_number的最大值的行。

就是这样,两对(accepted, register_date)(a, b)

(c, d)

返回查询,(a, b) < (c, d) if (a < c) or (a = c and b < d) (accepted, register_date)的条件小于同一对l的条件是加入条件的一部分。

由于n,当一行LEFT JOIN(左表)在l(右表)中没有匹配时,一行满{{1}而是使用s(对于n的列。)

联接条件将NULL中的所有行与来自n的{​​{1}}行匹配l并且更高 n部分。 id_number的最大值为(accepted, register_date)的{​​{1}}行在l中不会与(accepted, register_date)完成匹配。

n子句仅保留从NULL中选择的列中包含WHERE的行,这意味着它们在{{1}上具有最大值对。

最后,NULL子句从左表n中提取所需的列((accepted, register_date)的列都是SELECT。)

使用其他l条件完成查询(如果需要)并添加相应的n表达式以获得所需顺序的行。