相同的查询 returns 不同的结果(MySQL 分组依据)
Same Query returns different results (MySQL Group By)
这只发生在 ORDER BY
之后强制 GROUP BY
的查询。
目标:
为给定的 cardID
.
每个 unit
获取 latest balance
Table:
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
升级到MySQLv5.7.13后,结果returns初始余额;就好像给定的卡没有扣除。
这是 MySQL 版本中的错误吗?
你能推荐任何其他更可靠的方法来解决这个问题吗?
这是您使用数据库的错误。 MySQL 非常明确,当您在聚合查询的 SELECT
子句中包含列时——它们不在 GROUP BY
中——那么它们来自 indeterminate 行。
这种语法是 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)
上使用索引。
根据 cardId
、unit
和 date
的降序添加行号只是另一个角度。
查询
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;
这只发生在 ORDER BY
之后强制 GROUP BY
的查询。
目标:
为给定的 cardID
.
unit
获取 latest balance
Table:
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
升级到MySQLv5.7.13后,结果returns初始余额;就好像给定的卡没有扣除。
这是 MySQL 版本中的错误吗?
你能推荐任何其他更可靠的方法来解决这个问题吗?
这是您使用数据库的错误。 MySQL 非常明确,当您在聚合查询的 SELECT
子句中包含列时——它们不在 GROUP BY
中——那么它们来自 indeterminate 行。
这种语法是 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)
上使用索引。
根据 cardId
、unit
和 date
的降序添加行号只是另一个角度。
查询
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;