Same Query返回不同的结果(MySQL Group By)

时间:2016-08-02 12:02:59

标签: mysql group-by sql-order-by

这仅适用于在GROUP BY之后强制ORDER BY的查询。

目标:

为给定balance的每个unit获取最新 cardID

表:

cardID  |  unit     |  balance  |  date
--------|-----------|-----------|--------------
A1      |  DEPOSIT  |  100      |  2016-05-01
A1      |  DEPOSIT  |  90       |  2016-05-02
A1      |  DEPOSIT  |  80       |  2016-05-03
A1      |  DEPOSIT  |  75       |  2016-05-04
A1      |  MINUTE   |  1000     |  2016-05-01
A1      |  MINUTE   |  900      |  2016-05-02
A1      |  MINUTE   |  800      |  2016-05-03

查询:

SELECT * FROM (
    SELECT unit, balance
    FROM cardBalances
    WHERE cardID = 'A1'
    ORDER BY date DESC
) AS cb
GROUP BY cb.unit;

预期结果(MySQL v5.5.38):

unit     |  balance  
---------|-----------
DEPOSIT  |  75       
MINUTE   |  800      

意外结果(MySQL v5.7.13):

unit     |  balance
---------|-----------
DEPOSIT  |  100
MINUTE   |  1000

升级到MySQL v5.7.13后,结果返回初始余额;好像给定的卡没有扣除。

这是MySQL版本中的错误吗? 你会建议任何其他更可靠的解决方法吗?

2 个答案:

答案 0 :(得分:2)

这是您使用数据库时的错误。 MySQL非常明确,当您在聚合查询中的SELECT子句中包含列时 - 并且它们不在GROUP BY中 - 那么它们来自不确定行。

此类语法特定于MySQL。学习它不仅是一个坏主意,而且通常在其他数据库中不起作用。

你可以通过各种方式做你想做的事。这是一个:

SELECT cb.*
FROM cardBalances cb
WHERE cardId = 'A1' AND
      cb.date = (SELECT MAX(date)
                 FROM cardBalances cb2
                 WHERE cb2.cardId = 'A1' AND cb2.unit = cb.unit
                );

这样做的好处是它可以使用cardBalances(unit, CardId, date)上的索引。

答案 1 :(得分:0)

通过根据cardIdunitdate的降序添加行号,只是另一个视角。

<强>查询

select t1.unit, t1.balance from 
(
    select cardId, unit, balance, `date`, 
    (
        case unit when @curA
        then @curRow := @curRow + 1 
        else @curRow := 1 and @curA := unit end 
    ) + 1 as num 
    from cardBalances t, 
    (select @curRow := 0, @curA := '') r 
    order by cardId, unit, `date` desc 
)t1 
where t1.num = 1
order by t1.unit;

SQL Fiddle Demo