为什么GROUPBY with LEFT JOIN会更改此MySQL查询的结果?

为什么GROUPBY with LEFT JOIN会更改此MySQL查询的结果?,mysql,Mysql,为了保护客户机信息的隐私,我将表名和字段名重写为通用名,并将问题减少到最小表达式。这意味着这里的GROUP BY可能没有意义,但它在更大的范围内有意义(因为原始查询有更多选择的值) 数据: 为什么这两个查询返回带有[*]标记的行的不同值 A)无分组依据 SELECT COUNT(table1.id) AS cnt1, COUNT(table2.id) AS cnt2, (SELECT COUNT(table2_copy.id) FROM table2 table2_copy

为了保护客户机信息的隐私,我将表名和字段名重写为通用名,并将问题减少到最小表达式。这意味着这里的
GROUP BY
可能没有意义,但它在更大的范围内有意义(因为原始查询有更多选择的值)

数据:

为什么这两个查询返回带有[*]标记的行的不同值

A)
分组依据

SELECT COUNT(table1.id) AS cnt1, COUNT(table2.id) AS cnt2,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt3,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        LEFT JOIN table3 ON table2_copy.some_id_2 = table3.id /*[*]*/
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt4
FROM table1
INNER JOIN table2 ON (table1.id = table2.id)
WHERE table1.id = 100
SELECT COUNT(table1.id) AS cnt1, COUNT(table2.id) AS cnt2,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt3,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        LEFT JOIN table3 ON table2_copy.some_id_2 = table3.id /*[*]*/
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt4
FROM table1
INNER JOIN table2 ON (table1.id = table2.id)
WHERE table1.id = 100 GROUP BY table1.id /* <-- THE ONLY DIFFERENCE */
返回:

array(1) {
  [0]=>
  array(4) {
    ["cnt1"]=>
    string(1) "1"
    ["cnt2"]=>
    string(1) "1"
    ["cnt3"]=>
    string(1) "2"
    ["cnt4"]=>
    string(1) "2" // Differs from cnt3 query only because of the [*] line
  }
}
array(1) {
  [0]=>
  array(4) {
    ["cnt1"]=>
    string(1) "1"
    ["cnt2"]=>
    string(1) "1"
    ["cnt3"]=>
    string(1) "2"
    ["cnt4"]=>
    string(1) "0" // <-- DIFFERENT
  }
}

B)
分组依据

SELECT COUNT(table1.id) AS cnt1, COUNT(table2.id) AS cnt2,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt3,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        LEFT JOIN table3 ON table2_copy.some_id_2 = table3.id /*[*]*/
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt4
FROM table1
INNER JOIN table2 ON (table1.id = table2.id)
WHERE table1.id = 100
SELECT COUNT(table1.id) AS cnt1, COUNT(table2.id) AS cnt2,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt3,
    (SELECT COUNT(table2_copy.id) FROM table2 table2_copy
        LEFT JOIN table3 ON table2_copy.some_id_2 = table3.id /*[*]*/
        WHERE table2_copy.some_id_1 = table2.id
    ) AS cnt4
FROM table1
INNER JOIN table2 ON (table1.id = table2.id)
WHERE table1.id = 100 GROUP BY table1.id /* <-- THE ONLY DIFFERENCE */
它的工作原理与我预期的一样:
cnt4
2


此外,这些查询(无表2):

以及:

返回两个:

array(1) {
  [0]=>
  array(3) {
    ["cnt1"]=>
    string(1) "1"
    ["cnt3"]=>
    string(1) "2"
    ["cnt4"]=>
    string(1) "2"
  }
}
所以问题似乎是这三条线的结合:

SELECT (SELECT ...
    LEFT JOIN ... /* THIS LINE */
...) FROM ...
INNER JOIN ... /* THIS LINE */
WHERE ...
GROUP BY ... /* AND THIS LINE */
谢谢。

注意:仅适用于
MySQL

分组依据
是按顺序返回结果,
不同
不是

groupby
以及
orderby NULL
DISTINCT
具有相同的效率(并以say方式实现)。如果要聚合(或区分)的字段上有索引,则这两个子句都会在此字段上使用松散索引扫描

在“分组依据”中,可以返回未分组和未聚合的表达式
MySQL
将从相应的组中选取任意随机值来计算表达式


使用
groupby
,可以从
SELECT
子句中省略
groupby
表达式。使用
DISTINCT
,您不能。
DISTINCT
返回的每一行都保证是唯一的。

您如何应用这些信息来回答这个问题?以不同的方式分组,使用聚合和不使用聚合。由于我没有任何表数据,我无法给出确切的信息,说明为什么在使用group by时第三行得到2。好的,我会尝试将数据添加到问题中。我需要更多信息来确定,但我确信这是因为group by不包括所有选定的列。Mysql只是在本例中有多行可用时选择行。谢谢Sebas。是的,但是如果只有一行可供选择怎么办?情况就是这样(在
WHERE
条件中检查),所以我不明白发生了什么。顺便说一句,我不知道你什么时候开始阅读这个问题,但是数据是在一开始上传的。我很好奇一件事。请在WHERE子句中添加
和table2.id=100
,如果有,请告诉我change@Sebas没有变化:cnt4仍然是0:/我不明白的是,如果我从一开始就创建了all(在一个新数据库中),它工作得很好:cnt4始终是2,但在我的数据库里它不是。。。
array(1) {
  [0]=>
  array(3) {
    ["cnt1"]=>
    string(1) "1"
    ["cnt3"]=>
    string(1) "2"
    ["cnt4"]=>
    string(1) "2"
  }
}
SELECT (SELECT ...
    LEFT JOIN ... /* THIS LINE */
...) FROM ...
INNER JOIN ... /* THIS LINE */
WHERE ...
GROUP BY ... /* AND THIS LINE */