我有那些表
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_count 和avg_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_count或 number_average 我只想ORDER BY 他们
保持查询像使用ORDER BY 一样不会影响查询性能,或者即使我不需要选择数据值,我仍然应该使用派生查询,因为顺序是正确的不管怎样还是派生查询在大表中会更快?
最佳答案
你真的在这里问了 2 个问题:
ORDER BY
子句是否影响查询性能- 为什么我的信数没有达到预期
无论哪种方式,要评估 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 yourSELECT
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/