2017-02-06 8 views
1

Мне нужен способ выбрать данные из таблицы A, объединить все, что имеет тот же индекс и обновить таблицу B, в результате которой будет получен результат конкатенации с индексом 1, в индексе 1 строки таблицы В.Как объединить данные с помощью определенного индекса и обновить вторую таблицу

Table A 
+-----------+------+-------+ 
| Type  | Name | Index | 
+-----------+------+-------+ 
| Cake  | A | 1  | 
+-----------+------+-------+ 
| Cookies | B | 1  | 
+-----------+------+-------+ 
| Ice Cream | C | 1  | 
+-----------+------+-------+ 
| Patatoes | D | 1  | 
+-----------+------+-------+ 
| Cake  | E | 2  | 
+-----------+------+-------+ 
| Cookies | F | 2  | 
+-----------+------+-------+ 
| Ice Cream | G | 2  | 
+-----------+------+-------+ 
| Patatoes | H | 2  | 
+-----------+------+-------+ 

Финальный стол должен быть:

Table B 
+-------+---------------------------------------------+ 
| Index | Line          | 
+-------+---------------------------------------------+ 
| 1  | Cake A ; Cookies B; Ice Cream C, Patatoes D | 
+-------+---------------------------------------------+ 
| 2  | Cake E ; Cookies F; Ice Cream G, Patatoes H | 
+-------+---------------------------------------------+ 

Можете ли вы помочь мне, пожалуйста? Благодаря

+1

Какая версия Oracle? Если 11g или выше, просмотрите функцию 'listagg' в документации. На этом сайте также много примеров. Если вы застряли, покажите нам, что вы пробовали, и что с ним не так. (Если вы все еще используете более раннюю версию, есть несколько идей [здесь] (https://oracle-base.com/articles/misc/string-aggregation-techniques)). –

ответ

1

Предполагая, что вы имели в виду поставить запятую вместо точки с запятой в вашей ожидаемого результата, вы можете использовать listagg:

select 
    "Index", 
    listagg(Type ||' '||Name, ', ') within group (order by Name) Line 
from table_a 
group by "Index"; 

Чтобы сделать обновление на TABLE_B, вы можете использовать merge:

merge into table_b b 
using (
    select 
     "Index", 
     listagg(Type ||' '||Name, ', ') within group (order by Name) Line 
    from table_a 
    group by "Index" 
) a on (
    b."Index" = a."Index" 
) 
when matched then update 
set b.Line = a.Line; 
+0

Выбор работает просто отлично. Но как мне сделать обновление после? Потому что этот выбор дает мне столько строк, сколько у меня индексов. Мне нужно сделать цикл? – UcanDoIt

+0

@UcanDoIt - см. Обновление. – GurV

+0

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

0

Просто вариант сверху. Здесь я использовал функцию WM_CONCAT для согласования значений на основе индекса. Примечание: WM_CONCAT is oracle Недокументированная функция может не работать, если объект отсутствует в базе данных. Надеюсь, это тоже поможет.

select idx, 
    wmsys.wm_concat(Typ) line -- This is Oracle undocumented function so may not work if this object not present in database 
FROM 
    (SELECT 'Cake' typ,'A' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Cookies' typ,'B' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Ice Cream' typ,'C' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Cake' typ,'D' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Cake' typ,'E' name,2 idx FROM dual 
    UNION ALL 
    SELECT 'Cookies' typ,'F' name,2 idx FROM dual 
    UNION ALL 
    SELECT 'Ice Cream' typ,'G' name,2 idx FROM dual 
) 
GROUP BY idx; 


MERGE INTO TABLEB USING 
(SELECT idx, 
    wmsys.wm_concat(Typ) line 
FROM 
    (SELECT 'Cake' typ,'A' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Cookies' typ,'B' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Ice Cream' typ,'C' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Cake' typ,'D' name,1 idx FROM dual 
    UNION ALL 
    SELECT 'Cake' typ,'E' name,2 idx FROM dual 
    UNION ALL 
    SELECT 'Cookies' typ,'F' name,2 idx FROM dual 
    UNION ALL 
    SELECT 'Ice Cream' typ,'G' name,2 idx FROM dual 
) 
GROUP BY idx 
)a ON (a.idx = tableb.idx) 
WHEN matched THEN 
    UPDATE SET tableb.line = a.line;