更多的是一个有趣的问题,而不是我想用的东西
假设我运行以下查询:
SELECT su.id, su.name, sua.line_1, sua.line_2
FROM site_user su
JOIN site_user_address sua
ON sua.user_id = su.id
WHERE su.id = 1
GROUP BY su.id /* id is the PK for site_user */sua.line_1和sua.line_2肯定会从同一个site_user_address行返回吗?
我知道,至少site_user_address行是任意选择的
我在文档中找不到任何东西,也想不出一个可靠的方法来测试这个
更新
据我所知,这不是一个复制品。我想知道,在从同一个表中选择两个不同的列时,值的任意选择是否来自同一个任意选择的行
其他问题似乎不那么具体,更多的是针对一个或多个非聚合列的行和值的任意选择。
发布于 2018-09-28 17:06:35
您确实在利用臭名昭著的非标准MySQL GROUP BY实现。要获得更多信息,请阅读此https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html
对于第二个表中的值,您的查询相当于ANY_VALUE(),如下所示。
SELECT su.id, su.name,
ANY_VALUE(sua.line_1) line_1,
ANY_VALUE(sua.line_2) line_2
FROM site_user su
JOIN site_user_address sua
ON sua.user_id = su.id
WHERE su.id = 1
GROUP BY su.id只要site_user.id对每一行都是唯一的,您就会得到正确的名称,因为它依赖于id值。
但是对于另一个表中的值,您的结果,形式上来说,是不确定的或不可预测的。他们是从同一排回来的吗?不可预测。
不可预知是随机的,但更糟。随机意味着有时你会得到不同的值,所以你可以在测试中发现问题。不可预测意味着每次都会得到相同的值,直到没有。通常,当表和索引变大时,所选值的更改就会发生。
您可能希望使用提供可预测结果的查询。例如,这一次将返回site_user_address中值最高的site_user_address.id行。
SELECT su.id, su.name,
sua.line_1, sua.line_2
FROM site_user su
JOIN (
SELECT MAX(id) id, user_id
FROM site_user_address
GROUP BY user_id
) sumax ON su.id = sumax.user_id
JOIN site_user_address sua ON sumax.id = sua.id
WHERE su.id = 1 子查询:
SELECT MAX(id) id, user_id
FROM site_user_address
GROUP BY user_id检索每个site_user_address.id值的最大user_id值。然后,您可以加入到site_user_address表中,以提取这些id值的细节值。
避免了推断行为是设计成DBMS的诱惑,而不是文档化的行为,仅仅是因为您观察到了它们。你问题中的行为记录在案。文件上说这是不确定的。这意味着DBMS查询计划器可以自由地以最有效的方式满足您的查询。随着表和索引的增长,查询计划器可以并且确实选择不同的方式来满足相同的查询。不同的查询计划也可以来自驻留在缓存中的表的不同部分。等。等。
对于程序员来说,这种不可预见性很难将我们的大脑包围起来。我们不能容忍过程Java或php代码中的不可预测性。但是SQL是声明式的,成千上万的程序员已经花费了数千年的时间来使查询快速运行。即使您是迈克尔·斯通布雷克本人,也不要试图胜过DBMS。
https://stackoverflow.com/questions/52559594
复制相似问题