我试图根据时间戳数据类型的列字段对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
。
如何按更新列排序?
答案 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
这应该会给你你想要的结果。
您的尝试不起作用的原因,取决于mysql如何处理未在group by
子句中使用或在聚合函数中使用的字段的分组方式。
实际上,mysql允许您根据需要选择字段,大多数(如果不是全部)其他rdbms会在您尝试执行此操作时抛出错误。
12.16.3 MySQL Handling of GROUP BY会让你失望,但重要的部分就是:
您可以通过避免使用此功能来获得更好的性能 不必要的列排序和分组。但是,这很有用 主要是当每个非聚合列中的所有值都未命名时 GROUP BY对于每个组都是相同的。服务器可以自由选择 每个组中的任何值,因此除非它们相同,否则为值 选择是不确定的。
这就是为什么它没有选择你想要的日期或价值。
答案 1 :(得分:0)
您可以使用变量来确定每id
,attribute
的最高排名记录:
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
谓词将根据updated
,id
选择最近 attribute
值的记录。
修改强>
考虑到@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
答案 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;