mysql - 三个表的关系顺序是正确的,但值是错误的

标签 mysql sql left-join inner-join query-performance

我有那些表

     table1
|  id  |  name  |
|  1   |  axe   |
|  2   |  bow   |
|  3   |  car   |
|  4   |  dart  |


        table2                                        table3
|  t1_id  |  number  |                        |  t1_id  |  letter  |
|  1      |  5       |                        |  1      |  a       |
|  1      |  6       |                        |  1      |  b       |
|  1      |  2       |                        |  1      |  c       |
|  2      |  2       |                        |  2      |  a       |
|  2      |  2       |                        |  2      |  c       |
|  2      |  3       |                        |  2      |  r       |
|  3      |  8       |                        |  3      |  y       |
|  3      |  3       |                        |  3      |  i       |
|  3      |  1       |                        |  3      |  a       |
|  4      |  8       |                        |  4      |  a       |
|  4      |  9       |                        |  4      |  b       |
|  4      |  10      |                        |  4      |  c       |

并且table1(id)与table2(t1_id)、table3(t1_id)链接

我运行它让他们按最高字母数 匹配排序,然后按最高平均数 匹配排序以获得这个正确 结果http://www.sqlfiddle.com/#!9/69086b/8/0

SELECT 
  t1.id, 
  t1.name

FROM 
  table1 t1

INNER JOIN 
  table2 t2
    ON t2.t1_id = t1.id

LEFT JOIN 
  table3 t3
    ON t3.t1_id = t1.id
      AND t3.letter IN ('a', 'b', 'c')

GROUP BY
  t1.id

ORDER BY
  COUNT(t3.letter) DESC,
  AVG(t2.number) DESC

|  id  |  name  |
|  4   |  dart  |
|  1   |  axe   |
|  2   |  bow   |
|  3   |  car   |

一切正常


但是当我想检查查询是否有任何问题时,我决定检查letter_countavg_number 所以我使用了这个查询

SELECT 
  t1.id, 
  t1.name, 
  COUNT(t3.letter) AS letter_count, 
  AVG(t2.number) AS avg_number

FROM 
  table1 t1

INNER JOIN 
  table2 t2
    ON t2.t1_id = t1.id

LEFT JOIN 
  table3 t3
    ON t3.t1_id = t1.id
      AND t3.letter IN ('a', 'b', 'c')

GROUP BY
  t1.id

ORDER BY
  letter_count DESC,
  avg_number DESC

我期望的结果是

|  id  |  name  |  letter_count  |  avg_number   |
|  4   |  dart  |  3             |  9            |
|  1   |  axe   |  3             |  4.3333333333 |
|  2   |  bow   |  2             |  2.3333333333 |
|  3   |  car   |  1             |  4            |

但我得到的结果是http://www.sqlfiddle.com/#!9/69086b/3/0

|  id  |  name  |  letter_count  |  avg_number   |
|  4   |  dart  |  9             |  9            |
|  1   |  axe   |  9             |  4.3333333333 |
|  2   |  bow   |  6             |  2.3333333333 |
|  3   |  car   |  3             |  4            |

让我感到惊讶的是 letter_count 的相乘行,这可以通过派生查询 来解决,但我不想选择 letter_countnumber_average 我只想ORDER BY 他们

保持查询像使用ORDER BY 一样不会影响查询性能,或者即使我不需要选择数据值,我仍然应该使用派生查询,因为顺序是正确的不管怎样还是派生查询在大表中会更快?

最佳答案

你真的在这里问了 2 个问题:

  1. ORDER BY 子句是否影响查询性能
  2. 为什么我的信数没有达到预期

无论哪种方式,要评估 ORDER BY 子句,都需要评估表达式以便确定顺序。在您的第一个示例中,您需要指定表达式,因为这些列不包含在 SELECT 语句中。

然而,在您的第二个查询中,您已经选择了您想要排序的列,并且因为 ORDER BY 是在 AFTER 整个查询被处理后计算的,您可以简单地在 ORDER BY 子句中使用列 ALIAS,而不是再次执行函数。

some RDBMS query optimisers will convert your expressions in the ORDER BY statements to use the column alias for you IF you are ordering on expressions that exist in your SELECT clause

您这样做是对的,但是,由于响应中存在重复项,您的字母计数表达式不是最新的。

您可以简单地更改 COUNT 表达式以使用不同的子句来仅计算唯一值。

COUNT(DICTINCT t3.letter)

这使您的原始查询现在看起来像这样:

SELECT 
  t1.id, 
  t1.name

FROM 
  table1 t1

INNER JOIN 
  table2 t2
    ON t2.t1_id = t1.id

LEFT JOIN 
  table3 t3
    ON t3.t1_id = t1.id
      AND t3.letter IN ('a', 'b', 'c')

GROUP BY
  t1.id

ORDER BY
  COUNT(DICTINCT t3.letter) DESC,
  AVG(t2.number) DESC

关于mysql - 三个表的关系顺序是正确的,但值是错误的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57066277/

相关文章:

sql - 在 WHERE 子句中使用 OR 时,行将从 LEFT JOIN 中删除

mysql - freebsd 在 drupal 安装时缺少 mysql 选项

MySQL parse Column 得到一个数值段并相加

mysql - Drupal + phpBB 评论最多的用户

sql - 我很困惑为什么我的查询没有返回正确的项目

sql - 在 Liquibase 中可以在 splitstatements 上有一个空行吗?

mysql - LEFT JOIN 为 NULL 条件

php - 我无法从已经使用 GROUP BY 的表中循环记录

mysql - Sequelize defaultValue 未设置

Mysql 排名靠左 JOIN