Reputation: 13511
I have two tables with the following structure:
|=================|
| posts |
|=================|
| ID | Title |
|-----------------|
| 1 | Title #1 |
|-----------------|
| 2 | Title #1 |
|-----------------|
| 3 | Title #1 |
|-----------------|
| 4 | Title #1 |
|-----------------|
| 5 | Title #1 |
|-----------------|
and
|==========================================|
| meta |
|==========================================|
| id | post_id | meta_key | meta_value |
|------------------------------------------|
| 1 | 1 | key_one | value for #1 |
|------------------------------------------|
| 2 | 1 | key_two | value for #1 |
|------------------------------------------|
| 3 | 1 | key_three | value for #1 |
|------------------------------------------|
| 4 | 2 | key_one | value for #2 |
|------------------------------------------|
| 5 | 2 | key_three | value for #2 |
|------------------------------------------|
| 6 | 3 | key_one | value for #3 |
|------------------------------------------|
| 7 | 3 | key_three | value for #3 |
|------------------------------------------|
and I need to get the following single result:
|----------------------------------------------------------------|
| ID | Post Title | Meta Key One | Meta Key Two | Meta Key Three |
|----------------------------------------------------------------|
| 1 | Title #1 | value for #1 | value for #1 | value for #1 |
|----------------------------------------------------------------|
| 2 | Title #2 | value for #2 | null | value for #2 |
|----------------------------------------------------------------|
| 3 | Title #3 | value for #3 | null | value for #3 |
|----------------------------------------------------------------|
But I don't know how to do this.
The SQL Query I have build until now is this:
SELECT
`p`.`ID` AS `ID`,
`p`.`Title` AS `Post Title`,
`mt1`.`meta_value` AS `Meta Key One`,
`mt2`.`meta_value` AS `Meta Key One`,
FROM
posts AS `p`
LEFT JOIN `meta` AS `mt1` ON ( `p`.`ID` = `mt1`.`post_id` )
LEFT JOIN `meta` AS `mt2` ON ( `p`.`ID` = `mt2`.`post_id` )
WHERE
1 = 1
AND `mt1`.`meta_key` = 'key_one'
AND `mt2`.`meta_key` = 'key_three';
The problem is that if I add a third LEFT JOIN
in meta
table to use it later on in WHERE
clause and say mt1.meta_key = 'key_two'
I get only one record instead of three.
Does anyone know how can I achieve this with a single query ?
I don't know if that helps, but I have create an SQL Fiddle here : http://sqlfiddle.com/#!9/af591f/1
Note that the column names in fiddle doesn't meet the ones in my example, but the problem remains the same.
Upvotes: 2
Views: 76
Reputation: 17289
http://sqlfiddle.com/#!9/af591f/4
SELECT
`b`.`id` AS `ID`,
`b`.`title` AS `Title`,
mt1.meta_value `KeyOne`,
mt2.meta_value `KeyTwo`,
mt3.meta_value `KeyThree`
FROM
`base` as `b`
LEFT JOIN `meta` mt1 ON b.id = mt1.base_id AND mt1.meta_key = 'key_one'
LEFT JOIN `meta` mt2 ON b.id = mt2.base_id AND mt2.meta_key = 'key_two'
LEFT JOIN `meta` mt3 ON b.id = mt3.base_id AND mt3.meta_key = 'key_three'
Upvotes: 2
Reputation: 1943
Try this:
SELECT
`p`.`ID` AS `ID`,
`p`.`Title` AS `Post Title`,
`mt1`.`meta_value` AS `Meta Key One`,
`mt2`.`meta_value` AS `Meta Key Two`,
`mt3`.`meta_value` AS `Meta Key Three`
FROM
posts AS `p`
LEFT JOIN `meta` AS `mt1`
ON ( `p`.`ID` = `mt1`.`post_id` AND `mt1`.`meta_key` = 'key_one')
LEFT JOIN `meta` AS `mt2`
ON ( `p`.`ID` = `mt2`.`post_id` AND `mt2`.`meta_key` = 'key_two')
LEFT JOIN `meta` AS `mt3`
ON ( `p`.`ID` = `mt3`.`post_id` AND `mt3`.`meta_key` = 'key_three')
Upvotes: 1
Reputation: 72175
You can use conditional aggregation for this:
SELECT p.ID, p.Title AS 'Post Title',
MAX(CASE WHEN meta_key = 'key_one' THEN meta_value END) AS 'Meta Key One',
MAX(CASE WHEN meta_key = 'key_two' THEN meta_value END) AS 'Meta Key Two',
MAX(CASE WHEN meta_key = 'key_three' THEN meta_value END) AS 'Meta Key Three'
FROM posts AS p
LEFT JOIN meta AS m ON p.ID = m.post_id
GROUP BY p.ID, p.Title
The benefit of this method is that you use LEFT JOIN
just once, so it is easily extensible in order to accommodate additional key values.
Upvotes: 4
Reputation: 23379
You join tables by column, you don't join columns by columns.. Since you only have two tables you only need one join. Start with this query and change the *
to whatever columns you need.
select
* --or whatever
from
posts p
left join meta m on p.id = m.post_id
Upvotes: 1