i have this table
table1
| id | name |
| 1 | axe |
| 2 | bow |
| 3 | car |
| 4 | dart |
and these two tables
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 |
where in it t1_id is the table1 id
what i want to do is to get all table1 records having table3 letters a b c and the avg of their numbers like this order by the letter_count DESC first then by the avg_numbers 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 |
the query i expected to work properly was http://www.sqlfiddle.com/#!9/69086b/3/0
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
but numbers are totally different and in accurate but the order is correct
i don't want to get the letter_count and avg_number values but i just want to order by them but their values are worrying me with the query performance
i wouldn't notice this weird values because my actual query is
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
which only gives me proper ordery
| id | name |
| 4 | dart |
| 1 | axe |
| 2 | bow |
| 3 | car |
but after checking the values i was surprsied by the letter_count do i just ignore the values and it wouldn't affect the performance in my big table?
You are aggregating over two different dimensions. This causes a Cartesian product. One way to fix this is to aggregate before joining:
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;