从MySql中的最新时间戳获取多列中的最大值

时间:2016-07-24 22:49:16

标签: mysql

我尝试在多个相似列中获取*usedpc值列表,并order desc以获取最严重的违规者。此外,我只需要为每个sys_id选择最近时间戳的值。 示例数据:

Sys_id | timestamp | disk0_usedpc | disk1_usedpc | disk2_usedpc
---
1  | 2016-05-06 15:24:10 | 75 | 45 | 35
1  | 2016-04-06 15:24:10 | 70 | 40 | 30
2  | 2016-05-06 15:24:10 | 23 | 28 | 32
3  | 2016-05-06 15:24:10 | 50 | 51 | 55  

期望的结果(例如假设为limit 2):

1 | 2016-05-06 15:24:10 | disk0_usedpc | 75
3 | 2016-05-06 15:24:10 | disk2_usedpc | 55

我知道我可以使用greatestmax和组时间戳来获取每列的最大值,以便只获取最新值,但我无法弄清楚如何获得整个有序值列表(不仅是每列的最大/最大值,而是所有3个磁盘列中的" 5个最高值")。

编辑:我设置了一个SQLFiddle页面: http://sqlfiddle.com/#!9/82202/1/0

EDIT2:我很抱歉延误。我能够让所有三种解决方案都能正常工作,谢谢。如果@PetSerAl可以将他的解决方案放在一个答案中,我会将其标记为已接受,因为此解决方案使我能够非常顺利地进行自定义。

3 个答案:

答案 0 :(得分:1)

也许这样的东西会起作用......我知道它可能看起来很冗余,但它可以节省因为对同一个表进行多次连接而导致的开销:

SELECT md.Sys_id,
md.timestamp,
CASE
  WHEN
    md.disk0_usedpc > md.disk1_usedpc
      AND
    md.disk0_usedpc > md.disk2_usedpc
  THEN 'disk0_usedpc'
  WHEN
    md.disk1_usedpc > md.disk0_usedpc
      AND
    md.disk1_usedpc > md.disk2_usedpc
  THEN 'disk1_usedpc'
  ELSE 'disk2_usedpc'
END AS pcname,
CASE
  WHEN
    md.disk0_usedpc > md.disk1_usedpc
      AND
    md.disk0_usedpc > md.disk2_usedpc
  THEN md.disk0_usedpc
  WHEN
    md.disk1_usedpc > md.disk0_usedpc
      AND
    md.disk1_usedpc > md.disk2_usedpc
  THEN md.disk1_usedpc
  ELSE md.disk2_usedpc
END AS pcusage
FROM mydatabase md
GROUP BY md.Sys_id HAVING MAX(md.timestamp)
ORDER BY pcusage DESC

答案 1 :(得分:1)

试试这个:

select
    t1.sys_id, t1.`timestamp`,
    case locate(greatest(disk0_usedpc ,disk1_usedpc ,disk2_usedpc), concat_ws(',' ,disk0_usedpc ,disk1_usedpc ,disk2_usedpc))
        when 1 then 'disk0_usedpc'
        when 1 + length(concat(disk0_usedpc, ',')) then 'disk1_usedpc'
        when 1 + length(concat(disk0_usedpc, ',', disk1_usedpc, ',')) then 'disk2_usedpc'
    end as usedpc,
    greatest(disk0_usedpc ,disk1_usedpc ,disk2_usedpc) as amount
from yourtable t1
join (
    select max(`timestamp`) as `timestamp`, sys_id
    from yourtable 
    group by sys_id
) t2 on t1.sys_id = t2.sys_id and t1.`timestamp` = t2.`timestamp`
order by t1.`timestamp` desc
-- limit 2

SQLFiddle Demo

如何工作,这里的子查询是尝试获取每个组sys_id的最新行,作为许多解决方案中的一种方式。然后,您应该在disk0_usedpc ,disk1_usedpc ,disk2_usedpc中获得最佳列,正如您在问题中所写,函数greatest是计划。因此greatest(disk0_usedpc ,disk1_usedpc ,disk2_usedpc) as amount可以帮助您获得金额。

但是你也想要这个列的名称,我在这里使用locateconcatconcat_ws(这避免编写这么多的分隔符,这里是逗号{{1} })。

我们以行

,

为例:

1 | 2016-05-06 15:24:10 | 75 | 45 | 35会给我们" 75,45,35 ",此处此字符串中的75个索引是1,45是4,35是7。 如您所见,concat_ws(',' ,disk0_usedpc ,disk1_usedpc ,disk2_usedpc)将返回1,因此最大的行为locate(greatest(disk0_usedpc ,disk1_usedpc ,disk2_usedpc), concat_ws(',' ,disk0_usedpc ,disk1_usedpc ,disk2_usedpc)),此处为此。

答案 2 :(得分:1)

您可以将vm_disk表连接到三个行表,为每个磁盘创建单独的行。然后,由于现在每个磁盘都有行,您可以轻松地对它们进行过滤或排序。

select
  `sys_id`,
  `timestamp`,
  concat('disk', `disk`, '_usedpc') as `name`,
  case `disk`
    when 0 then `disk0_usedpc`
    when 1 then `disk1_usedpc`
    when 2 then `disk2_usedpc`
  end as `usedpc`
from
  `vm_disk` join
  (
    select 0 as `disk`
    union all
    select 1
    union all
    select 2
  ) as `t`
where
  (`sys_id`, `timestamp`) in (
    select
      `sys_id`,
      max(`timestamp`)
    from `vm_disk`
    group by `sys_id`
  )
order by `usedpc` desc
limit 5