0

给定这样的表:

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我发现了几个处理类似问题的线程,但它们都使用了子查询,这在我的情况下是没有选择的。

4

2 回答 2

4

不,依靠这个绝对不安全。事实上,这种构造在逻辑上是没有意义的(它是无效的 SQL),而且 MySql 仍然允许你这样做的事实是......不好。这是手册的摘录:

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

如果要获取最后一行和一个总和,则只需使用两个单独的查询:一个用于最后一行,一个用于求和。

于 2013-08-26T13:40:32.690 回答
0

您的查询非常好。它只是不做你想做的事:

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

字段daydaily取自数据中的任意行。在group by之后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了一个字符串。如果你想要它作为一个数字,把它转换回来。

于 2013-08-26T13:43:17.227 回答