"Схлопнуть" значения в столбце

Electroflower

Ребят, всем привет! Нужна помощь начинающему базисту.Суть проблемы: Есть запрос вида:
SELECT
ROWNUM rwnmbr,
NAME, 
ZNACH1,
ZNACH2
FROM /*далее запрос*/
, результатом которого является таблица следующего вида:_______________________ 1 NAME1 ZNACH11 ZNACH21 2 NAME1 ZNACH12 ZNACH22 3 NAME2 ZNACH13 ZNACH23 4 NAME2 ZNACH14 ZNACH24 5 NAME2 ZNACH15 ZNACH25 6 NAME3 ZNACH16 ZNACH26При этом в столбце "NAME" есть одинаковые имена. Мне нужно каким-то образом "схлопнуть" одинаковые значения, чтобы получить таблицу вида:_________________________ 1 NAME1 ZNACH11 ZNACH21 ZNACH12 ZNACH22 2 NAME2 ZNACH13 ZNACH31 ZNACH14 ZNACH41 ZNACH15 ZNACH51 3 NAME3 ZNACH16 ZNACH61Честно говоря, чувствую что вопрос простой, либо таким кажется, в любом случае у меня уже нет идей.
10 ответов

Electroflower

В MySQL есть GROUP_CONCAT(), а что в Вашей - нужно смотреть, в некоторых аналогов нет.


Electroflower

У меня Oracle 11.2.0.3.0.


Electroflower

Здравствуйте!Мне кажется вот такое решение Вам может подойти:1. Исходные данные:
SELECT * FROM t3;
N_NAME	N_VALUE1	N_VALUE2
1	name1	11		21
2	name1	12		22
3	name2	13		23
4	name2	14		24
5	name2	15		25
6	name3	16		26
2. Применяем запрос:
SELECT t.n_name AS nname,
       (listagg(t.n_value1, ', ') WITHIN GROUP (ORDER BY t.n_name)) || ', ' ||
       (listagg(t.n_value2, ', ') WITHIN GROUP (ORDER BY t.n_name)) AS nval
FROM t3 t
GROUP BY t.n_name
;
NNAME	NVAL
1	name1	11, 12, 21, 22
2	name2	13, 14, 15, 23, 24, 25
3	name3	16, 26


Electroflower

Нужно получить немного другое, при отправке сообщения куда-то делась табуляция...Исходная таблица:Конечная таблица:


Electroflower

Значит надо использовать слегка модифицированный селект, ранее предложенный orion2014 (без конкатенации)
SELECT t.n_name AS nname,
       (listagg(t.n_value1, ', ') WITHIN GROUP (ORDER BY t.n_name))   AS znach1,
       (listagg(t.n_value2, ', ') WITHIN GROUP (ORDER BY t.n_name))   AS znach2
FROM t3 t
GROUP BY t.n_name
;
Если вдруг в 11 версии Oracle еще нет функции listagg, то там точно есть в схеме WMSYS функция WM_CONCAT. У нее немного другой синтаксис, но принцип аналогичный
SELECT t.n_name AS nname,
       wmsys.wm_concat(t.n_value1)  AS znach1,
       wmsys.wm_concat(t.n_value2)  AS znach2
FROM t3 t
GROUP BY t.n_name
;
Насколько я помню, отличия в том, что внутри lislagg нельзя использовать опцию DISTINCT, а внутри wm_concat DISTINCT использовать можно. То есть, если нужно исключить повторяющиеся значения, то можно написать
SELECT t.n_name AS nname,
       wmsys.wm_concat(DISTINCT t.n_value1)  AS znach1,
       wmsys.wm_concat(DISTINCT t.n_value2)  AS znach2
FROM t3 t
GROUP BY t.n_name
;


Electroflower

Причем тут рваные галоши?
При том, что если учесть rownum, то выглядит это как "поместить в одну строку две подстроки"


Electroflower

выглядит это как "поместить в одну строку две подстроки"
Нет, это выглядит как "убрать лишние значения, чтобы не мозолили глаза". Тоже можно сделать
SELECT CASE WHEN mm=1 THEN kk ELSE NULL END   AS num,
       CASE WHEN mm=1 THEN  N_NAME ELSE NULL END   AS N_NAME,
       N_VALUE1, N_VALUE2,  nn
FROM (
SELECT N_NAME, N_VALUE1, N_VALUE2, 
       ROW_NUMBER() OVER (ORDER BY N_NAME) nn,
       dense_rank() OVER (ORDER BY N_NAME)  kk,
       ROW_NUMBER() OVER (partition BY N_NAME ORDER BY rownum) mm
) ORDER BY nn


Electroflower

В вашем варианте он пишет несколько значений, которые должны быть в разных строках...(Но это лучше чем ничего) А мне нужно именно как в таблицах, чтобы он лишний раз не перечислял имена, если в следующей строке оно повторяется..


Electroflower

Но это, конечно не "схлопнуть значения", поскольку полное число строк то же самое


Electroflower

AGK, спасибо большое за идею! Интересное решение, не знаю сколько бы мне пришлось его достигать..