假设您有这样的查询:
SELECT g, v
FROM t
GROUP BY g;
在这种情况下,对于g的每个可能值,mysql选择v的对应值之一。
但是,选择哪种取决于具体情况。
我在某处读到,对于每组g,将保留v的第一个值,其顺序是如何将记录插入表v。
这很丑陋,因为表中的记录应视为元素顺序无关紧要的集合。 这是如此“ mysql-ish” ...
如果要确定保留v的哪个值,则需要为v应用子选择,如下所示:
SELECT g, v
FROM (
SELECT *
FROM t
ORDER BY g, v DESC
) q
GROUP BY g;
这样,您可以定义外部查询处理子查询记录的顺序,因此您可以信任它将为v的单个值选择哪个值v。
但是,如果您需要一些WHERE条件,请非常小心。 如果将WHERE条件添加到子查询中,则它将保留该行为,它将始终返回您期望的值:
SELECT g, v
FROM (
SELECT *
FROM t
WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
ORDER BY g, v DESC
) q
GROUP BY g;
这就是您所期望的,子选择过滤并排序表。 它保留v具有给定值的记录,外部查询返回v和v的第一个值。
但是,如果将相同的WHERE条件添加到外部查询中,则会得到不确定的结果:
SELECT g, v
FROM (
SELECT *
FROM t
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
ORDER BY g, v DESC
) q
WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g;
令人惊讶的是,一次又一次执行相同的查询时,您可能会获得v的不同值,这很奇怪。 预期的行为是从子查询中以适当的顺序获取所有记录,在外部查询中对其进行过滤,然后选择与上一个示例中相同的记录。 但事实并非如此。
它似乎是随机选择v的值。 如果执行了更多(〜20)次但分布不均匀,则同一查询将为v返回不同的值。
如果不是指定外部WHERE,而是指定如下的HAVING条件:
SELECT g, v
FROM (
SELECT *
FROM t1
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
ORDER BY g, v DESC
) q
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g
HAVING g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9';
然后,您将再次获得一致的行为。
结论:我建议完全不要依赖这种技术。 如果您确实希望/需要避免在外部查询中使用WHERE条件。 如果可以,请在内部查询中使用它,或者在外部查询中使用HAVING子句。
我用以下数据进行了测试:
CREATE TABLE t1 (
v INT,
g VARCHAR(36)
);
INSERT INTO t1 VALUES (1, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');
INSERT INTO t1 VALUES (2, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');
在mysql 5.6.41中。
也许这只是在新版本中得到修复的错误,如果您有使用新版本的经验,请提供反馈。