在集体声明中依靠订单是否安全?

时间:2013-08-26 13:38:03

标签: mysql sql

给出一个这样的表:

id; day; daily
1; 2013-07-01; 50.00
1; 2013-07-02; 60.00
1; 2013-07-03; 70.00
1; 2013-07-04; 80.00

此查询:

SELECT
   id
   day,
   daily,
   SUM(daily) total
FROM
   table
GROUP BY
   id
ORDER BY
   day DESC

返回:

1; 2013-07-04; 80.00; 260.00

到目前为止一切都很好。

我的问题是:依靠order by语句对所有“未发表的”值是否安全?我需要确保我读取具有最高日期的行的“每日”的值。

谢谢,

彼得

PS我发现了几个处理类似问题的线程,但是他们都使用了子查询,这在我的情况下是没有选择的。

2 个答案:

答案 0 :(得分:4)

不,依靠这个绝对不安全。事实上,这种结构在逻辑上毫无意义(it is invalid SQL),并且MySql仍然允许你这样做的事实是......糟糕的。以下是手册的摘录:

  

但是,这主要适用于每个中的所有值   GROUP BY中未命名的非聚合列对于每个列都是相同的   组。 服务器可以自由选择每个组中的任何值,所以   除非它们相同,否则所选择的值是不确定的。   此外,不能从每个组中选择值   受添加ORDER BY子句的影响。对结果集进行排序   选择值后发生,ORDER BY不影响   服务器选择的每个组中的值。

如果你想获得最后一行和一个总和,那么只需使用两个单独的查询:一个用于最后一行,一个用于总和。

答案 1 :(得分:0)

您的查询完全没问题。它只是没有你想要的东西:

SELECT id, day, daily, SUM(daily) total
FROM table
GROUP BY id
ORDER BY day DESC;

字段daydaily取自数据中的任意行。在分组后,ORDER BY处理。执行所需操作的正确方法是使用子查询,或使用以下group_concat() / substring_index()方法:

SELECT id, max(day) as day,
       substring_index(group_concat(daily order by day desc), ',', 1) as daily,
       SUM(daily) as total
FROM table
GROUP BY id
ORDER BY day DESC;

这会将daily变成一个字符串。如果您想将其作为数字,请将其转换回来。