2015-11-21 5 views
3

У меня есть две таблицы для простоты таблицы A и таблицы B (обратите внимание, что я не имею права изменять структуру этих таблиц, поэтому я «Я задаю этот вопрос, чтобы обойти плохой дизайн базы данных».Связывание нескольких строк из таблицы B с одной строкой в ​​таблице A в MySQL

Таблица А имеет две колонки:

"id"   - is the unique identifier. 
"customer_id" - is the customer's ID. 

Так таблица А содержит список идентификаторов клиентов.

Таблица B содержит свойства о клиентах. Но это делает это странным образом (опять же, я не задал этого, и я не могу его изменить). Таблица B имеет [число] столбцов:

"id"   - is the unique identifier. 
"customer_id" - is the customer's ID. 
"key"   - is the name of the key/value pair 
"value"  - is the value of the key/value pair 

Так таблица B имеет пары ключ/значение, которые связаны с клиентами по их идентификаторам.

Я мог бы присоединиться к этим две таблицы, чтобы получить что-то вроде этого:

+----+-------------+------------+-------+ 
| id | customer_id | key  | value | 
+----+-------------+------------+-------+ 
| 0 | 5   | first_name | Bob | 
| 1 | 5   | last_name | Jones | 
| 2 | 6   | first_name | Sally | 
| 3 | 6   | last_name | Sue | 
+----+-------------+------------+-------+ 

Но как вы можете видеть, что может быть трудно управлять, поскольку информация о одного клиента на двух разных строках. Что было бы идеальным:

+----+-------------+------------+-----------+ 
| id | customer_id | first_name | last_name | 
+----+-------------+------------+-----------+ 
| 0 | 5   | Bob  | Jones  | 
| 1 | 6   | Sally  | Sue  | 
+----+-------------+------------+-----------+ 

Со всеми данными о пользователе в одной строке.

Есть ли способ сделать это в SQL-запросе, чтобы мне не приходилось сталкиваться с результатами в PHP? Или мне придется выбирать данные на PHP?

ответ

0

Одним из методов является условной агрегации:

select (@rn := @rn + 1) as id, customer_id, 
     max(case when `key` = 'first_name' then value end) as first_name, 
     max(case when `key` = 'last_name' then value end) as last_name 
from b cross join 
    (select @rn := 0) params 
group by customer_id; 

Я не уверен, что таблица a будет использоваться для, возможно, для фильтрации идентификаторов клиентов.

+0

мне нужно запрашивая из таблицы А, а не только В. В действительности, таблица А имеет больше данных, чем просто Customer_ID, и я буду хватать, что данных. –

+0

@ kylemorgan49. , , Вы можете использовать эти данные, используя 'join'. –

0

Использование GROUP_CONCAT или группы по

Select *,Group_concat(value) as full_name 
From b left join a on b.customer_id=a.customer_id 
Group by customer_id 
+0

Мне нужно, чтобы первое имя было отделено от фамилии, а не конкатенировано. –

0

Учитывая, что вы не можете изменить структуру таблицы, один подход заключается в использовании подзапросов на customer_id и key:

SELECT 
    tableA.id, 
    tableA.customer_id, 
    (
    SELECT 
     tableB.`value` 
    FROM tableB 
    WHERE tableB.customer_id = tableA.customer_id 
     AND tableB.`key` = 'first_name' 
) AS first_name, 
    (
    SELECT 
     tableB.`value` 
    FROM tableB 
    WHERE tableB.customer_id = tableA.customer_id 
     AND tableB.`key` = 'last_name' 
    ) AS last_name 
FROM tableA 

Примечание: С точки зрения производительности этой запрос может сосать. Но, если у вас нет вариантов, возможно, медленный запрос приведет людей, которые принимают решения, чтобы изменить структуру.

0

Это будет делать то, что вы хотите:

SELECT A.customer_id, B.value, B_1.value 
FROM (A INNER JOIN B ON A.customer_id = B.customer_id) 
INNER JOIN B AS B_1 ON B.customer_id = B_1.customer_id 
WHERE (((B.key)="first_name") AND ((B_1.key)="last_name"));