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

three tables relation order is correct but values are false

我有那些表

     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       |

and table1(id) 与 table2(t1_id), table3(t1_id)

i 运行 它让他们按 最高 letter_count 匹配然后按 最高 average_number 匹配以获得此 正确 结果 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 的乘积行,可以通过 派生查询 解决,但我不知道想要 select letter_countnumber_average 我只想 ORDER BY 他们

保持查询与使用 ORDER BY 一样只会影响查询性能,或者我是否仍应使用派生查询,即使我不需要 select 数据值,因为无论如何顺序都是正确的,或者派生查询在大表中会更快吗?

这将检索您需要的内容:

SELECT a.id, a.name, count(a.letter) letter_count, avg(a.number) avg_number
FROM( SELECT   
t1.id, 
t1.name, 
t3.letter, 
t2.number--,  
FROM 
table1 t1

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

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

GROUP BY
t1.id,  t1.name,  t3.letter, t2.number) a GROUP BY id, a.name

ORDER BY
letter_count DESC,
avg_number DESC

你在这里真的问了 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