2016-05-18 2 views
2

У меня есть две таблицы со следующей структурой:Как присоединиться к этим двум таблицам в MySQL

|=================| 
| posts   | 
|=================| 
| ID | Title  | 
|-----------------| 
| 1 | Title #1 | 
|-----------------| 
| 2 | Title #1 | 
|-----------------| 
| 3 | Title #1 | 
|-----------------| 
| 4 | Title #1 | 
|-----------------| 
| 5 | Title #1 | 
|-----------------| 

и

|==========================================| 
| 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 | 
|------------------------------------------| 

и мне нужно, чтобы получить следующий один результат:

|----------------------------------------------------------------| 
| 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 | 
|----------------------------------------------------------------| 

Но я не знаю, как это сделать.

SQL-запрос у меня есть не строить до сих пор это:

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'; 

Проблема заключается в том, что если добавить третий LEFT JOIN в meta таблицу, чтобы использовать его в дальнейшем в WHERE предложения и сказать mt1.meta_key = 'key_two' я получаю только один вместо трех.

Кто-нибудь знает, как я могу достичь этого с помощью одного запроса?

Я не знаю, если это помогает, но я создать SQL скрипки здесь: http://sqlfiddle.com/#!9/af591f/1

Обратите внимание, что имена столбцов в скрипке не удовлетворяют те, в моем примере, но проблема остается тем же ,

+1

По общему правилу: критерий по внешней присоединяемой таблице принадлежит в 'ON' пункта не в' WHERE' пункт. Здесь ваш запрос выходит из строя. –

ответ

2

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' 
+0

Вы должны использовать соединение OUTER для этого, потому что иначе вы не получите вторую и третью желаемую строку вывода. –

+1

вы можете проверить: http://stackoverflow.com/a/406333/4421474 нет никакой разницы между 'LEFT JOIN' и' LEFT OUTER JOIN' – Alex

1

Вы присоединяетесь к таблицам по столбцам, вы не присоединяетесь к столбцам по столбцам. Поскольку у вас есть только две таблицы, вам нужно только одно соединение. Начните с этого запроса и измените * на любые нужные столбцы.

select 
    * --or whatever 
from 
posts p 
left join meta m on p.id = m.post_id 
4

Вы можете использовать условную агрегацию для этого:

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 

Преимущество этого метода заключается в том, что вы используете LEFT JOIN только один раз, так что это легко расширяемый для размещения дополнительных ключевых значений.

Demo here

1

Попробуйте это:

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')