Mysql 从与第三个表相关的两个表中获取计算
我有这张桌子Mysql 从与第三个表相关的两个表中获取计算,mysql,left-join,inner-join,Mysql,Left Join,Inner Join,我有这张桌子 table1 | id | name | | 1 | axe | | 2 | bow | | 3 | car | | 4 | dart | 这两张桌子呢 table2 table3 | t1_id | number | | t1_id | letter | |
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 |
其中t1_id是表1 id
我想做的是得到所有表1记录,这些记录包含表3字母a b c和它们的数字的平均值,顺序如下:按字母计数| id | name | letter_count | avg_number |
| 4 | dart | 3 | 9 |
| 1 | axe | 3 | 4.3333333333 |
| 2 | bow | 2 | 2.3333333333 |
| 3 | car | 1 | 4 |
我希望能够正常工作的查询是
但数字完全不同,而且准确,但顺序是正确的
我不想得到字母计数和平均数值,但我只想按它们排序,但它们的值让我担心查询性能
我不会注意到这些奇怪的值,因为我的实际查询是
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 |
但是在检查了这些值之后,我被字母计数所超过了,我是否忽略了这些值,而这不会影响我的大表中的性能呢?您在两个不同的维度上进行聚合。这就产生了笛卡尔积。解决此问题的一种方法是在加入之前进行聚合:
在第三个表中,选择IN-SELECT子查询
SELECT
t1.id,
t1.name,
(
SELECT count(letter)
FROM t3
where t3.t1_id = t1.id
) as lettercount,
AVG(t2.number) AS avg_number
FROM
table1 t1
INNER JOIN
table2 t2
ON t2.t1_id = t1.id
如果我不需要
字母\u计数
和数字\u平均值
,是否可以使用我的查询,在这种情况下会更快?它的执行计划似乎比我不理解的派生表更好,它的行数是这里的两倍
SELECT t1.id, t1.name, t2.letter_count, t2.avg_number
FROM table1 t1 INNER JOIN
(SELECT t2.t1_id, AVG(t2.number) as avg_number
FROM table2 t2
GROUP BY t2.t1_id
) t2
ON t2.t1_id = t1.id LEFT JOIN
(SELECT t3.t2_id, COUNT(t3.letter) as letter_count
FROM table3 t3
WHERE t3.letter IN ('a', 'b', 'c')
GROUP BY t3.t2_id
) t3
ON t3.t1_id = t1.id
ORDER BY t3.letter_count DESC, t2.avg_number DESC;
SELECT
t1.id,
t1.name,
(
SELECT count(letter)
FROM t3
where t3.t1_id = t1.id
) as lettercount,
AVG(t2.number) AS avg_number
FROM
table1 t1
INNER JOIN
table2 t2
ON t2.t1_id = t1.id