Sample data from the genres table:
id | genre_name | genre | parent_id
---------------------------------------------
2 | Blues | MAIN | NULL
6 | Folk | MAIN | NULL
10 | Pop | MAIN | NULL
1032 | Easy Listening | SUBGENRE | 10
1067 | Pop Ballad | SUBGENRE | 10
1068 | Pop Rock | SUBGENRE | 10
Why doesn't the statements #1 and #2 (with the reflexive join) NOT return the parent?
-- Statement #1 only returns only the child rows.
SELECT
pg.id,
cg.*
FROM `genres` AS pg
LEFT JOIN `genres` AS cg
ON pg.id = cg.parent_genre_id OR (pd.id= NULL AND pg.id = 10)
WHERE pg.id = 10;
-- OUTPUT:
id | id | genre_name | genre | parent_id
--------------------------------------------------
10 | 1032 | Easy Listening | SUBGENRE | 10
10 | 1067 | Pop Ballad | SUBGENRE | 10
10 | 1068 | Pop Rock | SUBGENRE | 10
-- Statement #2 only returns only the child rows.
SELECT
pg.id,
cg.*
FROM `genres` AS pg
LEFT JOIN `genres` AS cg
ON pg.id = cg.parent_genre_id
WHERE pg.id = 10 AND pg.parent_genre_id IS NULL;
-- OUTPUT:
id | id | genre_name | genre | parent_id
--------------------------------------------------
10 | 1032 | Easy Listening | SUBGENRE | 10
10 | 1067 | Pop Ballad | SUBGENRE | 10
10 | 1068 | Pop Rock | SUBGENRE | 10
-- Statement #3 returns both parent and child rows.
(SELECT
id,
genre_name,
genre_type,
parent_genre_id
FROM `genres`
WHERE id = 10)
UNION -- Get all sub-genres (children)
(SELECT
cg.id,
cg.genre_name,
cg.genre_type,
cg.parent_genre_id
FROM `genres` AS pg
JOIN `genres` AS cg
ON pg.id = cg.parent_genre_id
WHERE pg.id = 10);
-- OUTPUT:
id | genre_name | genre | parent_id
---------------------------------------------
10 | Pop | MAIN | NULL
1032 | Easy Listening | SUBGENRE | 10
1067 | Pop Ballad | SUBGENRE | 10
1068 | Pop Rock | SUBGENRE | 10
The #3 statement seems like a bad use of UNION to me.
Warning, bad pun intended:
Now the term self-relationship sounds like it implies a certain thing people do with their hands below their belt; but in any case I would like to know why the first two selects do not cum up with the intended results. Rather disappointing after the query reached climax. Uh, I mean returns the results.
After the answer given below, I ended up using the UNION (no JOIN of course):
(SELECT
`id`,
`genre_name`,
`genre_type`,
`parent_genre_id`
FROM `genres`
WHERE `id` = 10)
UNION -- Get all sub-genres (children)
(SELECT
`id`,
`genre_name`,
`genre_type`,
`parent_genre_id`
FROM .`genres`
WHERE `parent_genre_id` = 10);
pd.iddoesn't exist becausepdis not an alias of anything as far as I can tell. Also= NULLis never going to work because NULL is never equal to anything (unless MySQL has different NULL semantics to civilised DBMS platforms). On #2 theAND pg.parent_genre_id IS NULLisn't going to add any more selectivity to the query on the data set. – ConcernedOfTunbridgeWells Mar 26 '12 at 12:31OR (pd.id= NULL AND pg.id = 10), the 'pd' was supposed to be a 'pg'. TheAND pg.parent_genre_id IS NULLwas just a desperation move, since I'm a NOVICE SQL'r. – b01 Mar 26 '12 at 13:36