为每个 ID 选择 MAX DATE
Posted
技术标签:
【中文标题】为每个 ID 选择 MAX DATE【英文标题】:SELECT MAX DATE for each ID 【发布时间】:2013-06-25 20:43:53 【问题描述】:我有两个叫“tipo_hh”和“tipo_hh_historial”。
我需要在两个表之间进行连接,其中两个表中的“id”相同。 但我需要为“tipo_hh”表中的每个“id”选择“tipo_hh_historial”表中的“valor”,条件是“fecha_cambio”和“hora_cambio”最大值的记录。
“id”是表“tipo_hh”中的主键和自增
类似的东西。
这是表“tipo_hh”
id nombre
1 Reefer
2 Lavados
3 Dry
4 Despacho
这是表格“tipo_hh_historial”
id valor fecha_cambio hora_cambio
1 1.50 27/06/2013 19:15:05
1 5.50 27/06/2013 19:19:32
1 5.50 27/06/2013 19:20:06
1 2.50 27/06/2013 21:03:30
2 4.66 27/06/2013 19:15:17
2 3.00 27/06/2013 19:20:22
3 5.00 27/06/2013 19:20:32
4 1.50 27/06/2013 19:20:50
我需要这个:
id nombre valor
1 Reefer 2.50
2 Lavados 3.00
3 Dry 5.00
4 Despacho 1.50
【问题讨论】:
请查看答案并接受... 【参考方案1】:首先,您应该为您的列使用正确的数据类型,例如日期应该有一列类型数据与您的示例数据集中的时间列相同,您的日期格式为'%d/%m/%Y'
id 这可以更改为标准格式'%Y-%m-%d'
这很好,所以下面的查询适用于列的正确类型
SELECT t.* ,new_tipo_hh_historial.`valor`
FROM tipo_hh_new t
JOIN (
SELECT th.*
FROM tipo_hh_historial_new th
JOIN (
SELECT id,valor,
MAX(fecha_cambio ) fecha_cambio
,MAX(hora_cambio) hora_cambio
FROM `tipo_hh_historial_new`
GROUP BY id
) thh
ON (
th.`id` =thh.`id`
AND th.fecha_cambio=thh.`fecha_cambio`
AND th.hora_cambio = thh.`hora_cambio`
)
) new_tipo_hh_historial
USING (id)
Fiddle Demo
如果您将日期和时间存储为字符串,那么您需要将它们格式化为真实类型,您可以在下面的查询中使用但不推荐
SELECT t.* ,new_tipo_hh_historial.`valor`
FROM tipo_hh t
JOIN (
SELECT th.*
FROM tipo_hh_historial th
JOIN (
SELECT id,valor,
MAX(STR_TO_DATE(fecha_cambio , '%d/%m/%Y')) fecha_cambio
,MAX(TIME_FORMAT(hora_cambio,'%H:%i:%s')) hora_cambio
FROM `tipo_hh_historial`
GROUP BY id
) thh
ON (
th.`id` =thh.`id`
AND STR_TO_DATE(th.fecha_cambio , '%d/%m/%Y')=thh.`fecha_cambio`
AND TIME_FORMAT(th.hora_cambio,'%H:%i:%s') = thh.`hora_cambio`
)
) new_tipo_hh_historial
USING (id)
Fiddle Demo
您的问题看起来像 greatest-n-per-group 问题,因此您可以首先从表中的最大值 tipo_hh_historial
中获取最大值 fecha_cambio
和 hora_cambio
并且需要在多个条件下自行加入获得像 ie 一样的最大值
ON (
th.`id` =thh.`id`
AND th.fecha_cambio=thh.`fecha_cambio`
AND th.hora_cambio = thh.`hora_cambio`
)
然后加入您的第一个表以获得预期结果
编辑:@Kickstart 发现的问题他已经回答了,所以我将提供另一种方法来克服。应该有一个字段来存储日期和时间的记录,如 fecha_cambio DATETIME
所以不会错过 id 并获得正确的日期和时间最大值。请参阅下面的更新查询
SELECT t.* ,new_tipo_hh_historial.`valor`
FROM tipo_hh_new t
JOIN (
SELECT th.*
FROM tipo_hh_historial_alter th
JOIN (
SELECT id,valor,
MAX(fecha_cambio ) fecha_cambio
FROM `tipo_hh_historial_alter`
GROUP BY id
) thh
ON (
th.`id` =thh.`id`
AND th.fecha_cambio=thh.`fecha_cambio`
)
) new_tipo_hh_historial
USING (id)
Updated fiddle demo
【讨论】:
感谢您的回复...我已经解决了我的问题...我用这篇文章解决了我的问题...jan.kneschke.de/projects/mysql/groupwise-max。我忘了注意这个问题中的日期字段......但是我在我的表中使用了日期数据类型......你为这两种情况都提供了解决方案。非常感谢您的努力...我将为您的回应和努力付出 50 分。再次感谢... 怕这个sql有bug。如果对于一个 id,最大 hora_cambio 不在最大 fecha_cambio 上,那么它会错过该 id 的值 @Kickstart 你发布了答案,而我正在使用相同的逻辑来克服你的观点 没问题。完全同意您的观点,单个日期时间字段会更好。 @downvoters 愿意解释您在答案中发现的问题【参考方案2】:使用子查询来获取每个id的历史记录的最大日期/时间,并使用它来获取其余的最新历史记录:-
SELECT tipo_hh.id, tipo_hh.nombre, tipo_hh_historial.valor
FROM tipo_hh
INNER JOIN
(
SELECT id, MAX(STR_TO_DATE(CONCAT(fecha_cambio, hora_cambio), '%d/%m/%Y%k:%i:%s')) AS MaxDateTime
FROM tipo_hh_historial
GROUP BY id
) Sub1
ON tipo_hh.id = Sub1.id
INNER JOIN tipo_hh_historial
ON tipo_hh_historial.id = Sub1.id
AND STR_TO_DATE(CONCAT(fecha_cambio, hora_cambio), '%d/%m/%Y%k:%i:%s') = Sub1.MaxDateTime
SQL 小提琴:-
http://www.sqlfiddle.com/#!2/68baa/2
【讨论】:
【参考方案3】:SELECT tipo_hh.id, tipo_hh.nombre, tipo_hh_historial.valor
FROM tipo_hh INNER JOIN tipo_hh_historial
ON tipo.id = tipo_hh_historial.id AS
group by tipo_hh_historial.id
Having max(tipo_hh_historial.hora_cambio);
【讨论】:
谢谢!......但这不是我需要的......因为我需要在每个“id”的最大“hora_cambio”和“fecha_cambio”的同一行中选择“valor”的值"【参考方案4】:试试这个:
SELECT A.id, B.nombre, A.valor, MAX(A.hora_cambio) AS hora_cambio_time
FROM tipo_hh_historial AS A
INNER JOIN tipo_hh AS B
ON(A.id = B.id)
GROUP BY A.id
【讨论】:
谢谢!......但这不是我需要的......因为我需要在每个“id”的最大“hora_cambio”和“fecha_cambio”的同一行中选择“valor”的值"以上是关于为每个 ID 选择 MAX DATE的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 case 语句中的函数返回值以选择每个函数的 MAX?
如何在 Oracle SQL 中不使用 distinct 选择从多个 max(case when) 派生的唯一行