I would like to get rid of "Using temporary; Using filesort"
One of the problems I see is that you're using different GROUP BY
and ORDER BY
clauses. From the manual on how MySQL uses temporary tables:
If there is an ORDER BY clause and a different GROUP BY clause, or if the ORDER BY or GROUP BY contains columns from tables other than the first table in the join queue, a temporary table is created.
As soon as you create a temporary table, it will need to be sorted according to your ORDER BY
clause, indicated by 'using filesort'.
This execution plan at leasts uses the indexes to appropriately limit the number of rows found.
I would also look through the docs on ORDER BY optimization.
First the author table, that's easy.
CREATE TABLE author (
authorid serial PRIMARY KEY,
username text UNIQUE
);
Now we use a self-referential post table to create the hierarchical structure.
CREATE TABLE posts (
id serial PRIMARY KEY,
parent_post int REFERENCES posts,
authorid int NOT NULL REFERENCES author,
body text NOT NULL
);
Test data...
INSERT INTO author (authorid,username) VALUES
(0, 'ecarroll'),
(1, 'jbob');
INSERT INTO posts (id,parent_post,authorid,body) VALUES
(0, null, 0, 'HALLO WORLD'),
(1 ,0, 1, 'HALLO EVAN' );
Recursive query to get it working.
WITH RECURSIVE t(chain,author_un,text,id) AS (
SELECT ARRAY[id], username, body, id
FROM posts
INNER JOIN author USING (authorid)
WHERE parent_post IS NULL
UNION ALL
SELECT t.chain||p.id, username, p.body, p.id
FROM t
INNER JOIN posts AS p
ON (t.id = p.parent_post)
INNER JOIN author AS a
USING (authorid)
)
SELECT *
FROM t;
chain | author_un | text | id
-------+-----------+-------------+----
{0} | ecarroll | HALLO WORLD | 0
{0,1} | jbob | HALLO EVAN | 1
(2 rows)
For more information on this method, see my post here
Best Answer
That should be simple with
array_agg
and additionalFILTER
clauses: