是否可以确保任意选择的非聚合列与MySQL GROUP BY来自同一行?

时间:2018-09-28 16:45:33

标签: mysql group-by

除了我要使用的东西以外,还有更多有趣的问题

说我运行以下查询:

  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_1sua.line_2从同一行site_user_address返回?

我知道,至少site_user_address行是任意选择的

我在文档中找不到任何内容,也无法想到一种可靠的测试方法

更新

据我所知,这不是重复项。.我想知道,当从同一张表中选择两个不同的列时,是否会任意选择来自同一行的值?

其他问题似乎不太具体,而是直接针对一个或多个非聚合列的行和值的任意选择

1 个答案:

答案 0 :(得分:2)

您确实在利用臭名昭著的GROUP BY的MySQL非标准实现。请阅读以获取更多信息https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html

您的查询等效于using 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是声明性的,并且数千名程序员已经进入使查询快速运行的阶段。即使您自己Michael Stonebraker,也不要试图超越DBMS。