2014-10-01 3 views
9

У меня есть две таблицы:Преобразование нескольких строк в столбцы в MySQL

TABLEA

+-------+--------+ 
| Data | Acc_No | 
+-------+--------+ 
| Unix |  10 | 
| Linux |  20 | 
+-------+--------+ 

TableB

+-----+----------+--------+ 
| Obj | Type  | Amount | 
+-----+----------+--------+ 
| 10 | rev  | 100.00 | 
| 10 | revision | 200.00 | 
+-----+----------+--------+ 

Я хочу, чтобы на выходе, как этот

+-------+--------+----------+--------+-----------+----------+ 
| Data | Acc_No | Type  | Amount | Type_1 | Amount_1 | 
+-------+--------+----------+--------+-----------+----------+ 
| Unix | 10  | rev  | 100 | revision | 200  | 
+-------+--------+----------+--------+-----------+----------+ 

Я пробовал делать это с помощью простого соединения. Вот запрос:

SELECT a.Data,a.Acc_No, b.Type, b.Amount, bb.Type AS "Type_1", bb.Amount AS "Amount_1" 
FROM TableA a,TableB b, TableB bb 
WHERE a.Acc_No = b.Obj AND 
     b.Obj = bb.Obj AND 
     bb.Obj = a.Acc_No AND 
     a.Acc_No =10; 

Но я получил этот выход.

+------+--------+----------+--------+----------+----------+ 
| Data | Acc_No | Type  | Amount | Type_1 | Amount_1 | 
+------+--------+----------+--------+----------+----------+ 
| Unix |  10 | rev  | 100.00 | rev  | 100.00 | 
| Unix |  10 | revision | 200.00 | rev  | 100.00 | 
| Unix |  10 | rev  | 100.00 | revision | 200.00 | 
| Unix |  10 | revision | 200.00 | revision | 200.00 | 
+------+--------+----------+--------+----------+----------+ 

Я пробовал искать ответ на этом сайте, и я даже искал его, но я не нашел для него правильного ответа.

+0

Волю два типа всегда будут 'rev' и' revision'? Будут ли другие типы? Будет ли более двух типов? – JNevill

+0

Нет, существует только два типа: rev и ревизия. Это всего лишь образец данных, но мой более высокий результат ожидает такого рода выход. – Am1t

ответ

5

Ваш текущий запрос близок, но я бы предложил несколько незначительных изменений, чтобы получить результат. Если вы хотите «сворачивать» данные с помощью JOINs, вам нужно будет различать, какое значение вы хотите вернуть из TableB в каждом последующем соединении.

Например, если вы хотите вернуть type=rev, вам необходимо указать конкретный фильтр для этого значения. Тогда вы сделаете то же самое с type=revision. Я также предлагаю использовать LEFT JOIN для присоединения к TableB, если у вас нет значений type для каждого Acc_no, тогда вы по-прежнему будете возвращать данные.

select 
    a.data, 
    a.acc_no, 
    b.type, 
    b.amount, 
    bb.type as type_1, 
    bb.amount as amount_1 
from tablea a 
left join tableb b 
    on a.acc_no = b.obj 
    and b.type = 'rev' 
left join tableb bb 
    on a.acc_no = bb.obj 
    and bb.type = 'revision'; 

См SQL Fiddle with Demo

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

select 
    a.data, 
    a.acc_no, 
    max(case when b.type = 'rev' then b.type end) as type, 
    max(case when b.type = 'rev' then b.Amount end) as Amount, 
    max(case when b.type = 'revision' then b.type end) as type_1, 
    max(case when b.type = 'revision' then b.Amount end) as Amount_1 
from tablea a 
left join tableb b 
    on a.acc_no = b.obj 
group by a.data, a.acc_no 
order by a.acc_no; 

См SQL Fiddle with Demo

+0

Большое спасибо за ваши усилия, но я хочу точный результат, как я показал в ожидаемом выходе. Как вы думаете, будет ли создаваться представление и отображать его содержимое? – Am1t

+0

@ Am1t Что значит, что вы хотите получить точный результат, который вы показали? Это дает точный результат, за исключением того, что я не фильтровал для 'acc_no = 10'. Что касается вашего второго вопроса, вы можете разместить это в представлении. – Taryn

+0

Я хочу только те данные, которые связаны с 'Acc_No = 10', но когда я выполняю вышеуказанный запрос, я получаю Linux, у которого есть' Acc_No = 20'. Поэтому фильтрация должна выполняться на основе 'Acc_No = 10'. – Am1t

Смежные вопросы