在My Sql中的timestamp列上排序 - 而不是varchar列

时间:2015-05-21 07:17:31

标签: mysql

我试图根据时间戳数据类型的列字段对SQL元组进行排序。

表格中的数据是这样的:

 id      attribute   value      updated
-------------------------------------------------
'3449'   'HEIGHT'    '12'      '2013-11-30 03:20:25'
'3449'   'HEIGHT'    '15'      '2013-12-10 03:20:25'


select *, count(1) as cnt from attribute_table 
where id ='3449'
group by id,attribute having cnt > 1
ORDER BY updated;

输出是这样的,无论我在ORDER BY语句的末尾添加ASC / DESC参数,结果都保持不变。

 id      attribute   value      updated
-------------------------------------------------
'3449'   'HEIGHT'    '12'      '2013-11-30 03:20:25'

更新列的数据类型为timestamp,而不是其他类似问题的varchar

如何按更新列排序?

3 个答案:

答案 0 :(得分:1)

这类问题的一般解决方案是两步过程。首先,找到每个id的最新行:

select id, attribute, max(updated) last_updated
  from <your_table>
  group by id, attribute

接下来,我们需要将该结果再次连接到表中以获取其余数据。

select t.*
  from <your_table> t
    inner join (
      select id, attribute, max(updated) last_updated
        from <your_table>
        group by id, attribute
    ) q
    on t.id = q.id
      and t.updated = q.last_updated
      and t.attribute = q.attribute

这应该会给你你想要的结果。

quick demo here

您的尝试不起作用的原因,取决于mysql如何处理未在group by子句中使用或在聚合函数中使用的字段的分组方式。

实际上,mysql允许您根据需要选择字段,大多数(如果不是全部)其他rdbms会在您尝试执行此操作时抛出错误。

12.16.3 MySQL Handling of GROUP BY会让你失望,但重要的部分就是:

  

您可以通过避免使用此功能来获得更好的性能   不必要的列排序和分组。但是,这很有用   主要是当每个非聚合列中的所有值都未命名时   GROUP BY对于每个组都是相同的。服务器可以自由选择   每个组中的任何值,因此除非它们相同,否则为值   选择是不确定的。

这就是为什么它没有选择你想要的日期或价值。

答案 1 :(得分:0)

您可以使用变量来确定每idattribute的最高排名记录:

SELECT id, attribute, value, updated
FROM (
SELECT value, updated,
       @row_number:= CASE WHEN @id = id AND @attr = attribute THEN @row_number+1
                          ELSE 1
                     END AS rn,
       @id:=id AS id,
       @attr:=attribute AS attribute
FROM attribute_table, (SELECT @row_number:=0, @id:=0, @attr:='') AS vars
ORDER BY id, attribute, updated DESC ) t
WHERE t.rn =1

rn = 1谓词将根据updatedid选择最近 attribute值的记录。

SQL Fiddle Demo

修改

考虑到@pala_的评论,这是查询的样子:

SELECT id, attribute, value, updated
FROM (
SELECT id, attribute, value, updated, 
       if (@id = id AND @attr = attribute, 
           if (@id:=id, 
              if (@attr:=attribute, @row_number:= @row_number + 1, @row_number:= @row_number + 1),
              if (@attr:=attribute, @row_number:= @row_number + 1, @row_number:= @row_number + 1)
           ),   
           if (@id:=id, 
              if (@attr:=attribute, @row_number:= 1, @row_number:= 1),
              if (@attr:=attribute, @row_number:= 1, @row_number:= 1)
           )   
       ) AS rn
FROM attribute_table, (SELECT @row_number:=0, @id:='', @attr:='') AS vars
ORDER BY id, attribute, updated DESC ) t
WHERE t.rn = 1

SQL Fiddle Demo

答案 2 :(得分:-1)

您正在使用聚合,mysql中的group by获取分组到一行的所有行的第一行。

由于有2行满足您的组条件,因此为结果集选择第一行(即顶部)。

不知何故,你需要把它放在首位。可能的转向是首先对结果集进行排序,将行置于顶部并执行分组。

 select *, count(1) as cnt from (select * from attribute_table order by 
 updated desc ) as alias 
 where id ='3449'
 group by id,attribute having cnt > 1
 ORDER BY updated;