#sql #sql-server #merge #sql-server-2016
#sql #sql-сервер #объединить #sql-server-2016
Вопрос:
У меня есть таблица со следующим макетом
Row ID Name Notes
1 100 A Full Text
2 200 B Full Text
3 300 C Text part1
4 Text part2
5 Text part3
6 400 D Full Text
Где время от времени содержимое ячейки Notes для строки заполнялось строками под ней (например, строка 3 содержит содержимое notes в строках 4 и 5.) Другими словами, строка 3 была последней «допустимой» строкой. Мне нужно объединить содержимое notes из строк 4 и 5 в строку 3. Как я могу объединить содержимое notes в одну строку (строка 3) и удалить больше не нужные строки (строки 4 и 5)? Таким образом, конечный продукт будет выглядеть следующим образом
Row ID Name Notes
1 100 A Full Text
2 200 B Full Text
3 300 C Full Text
6 400 D Full Text
Комментарии:
1. какая у вас версия sqlserver?
2. Если бы у вас была какая-то идентификация, которая показывает, что эти строки являются группами, тогда вы могли бы использовать String_Agg() . На данный момент нет ничего, что говорило бы о том, что строки с идентификатором 3,4,5 находятся в одной группе. В чем логика?
3. Зачем повторять
text3
3 раза, если каждый раз это будет одно и то же значение?4. @Fahmi смотрите тег.
5. @CetinBasoz Я обновил информацию о таблице
Ответ №1:
Вы можете использовать накопительный count()
для назначения групп, а затем агрегировать:
select row_number() over (order by min(row)) as row,
min(id) as id, min(name) as name,
string_agg(text, ' ') within group (order by row) as text
from (select t.*,
count(id) over (order by row) as grp
from t
) t
group by grp;
Редактировать:
В более старых версиях SQL Server вы можете использовать:
select min_row, id,
stuff( (select ' ' t.notes
from t t2
where t2.row >= i.min_row and
(t2.row < i.max_row or i.max_row is null)
for xml path ('')
), 1, 1, ''
) as notes
from (select id, name, min(row) as min_row, lead(min(row)) over (order by id) as max_row
from t
group by by id, name
) i;
Комментарии:
1. У меня другая среда, в которой выполняется SQL Server 2016. Как бы мне обойти отсутствие string_agg для 2016? @Gordon Linoff
2. @user3277752 . . . Есть ли у вас максимальное количество промежуточных строк?
3. Я не уверен, что вы имеете в виду? Исходная таблица состоит из 100 тысяч строк.
4. @user3277752 . . . Каково максимальное количество строк с
NULL
идентификаторами, которые необходимо объединить в одну строку?5. На беглый взгляд кажется, что это 60 строк.
Ответ №2:
Если вы используете Sql server 2016, то вы можете попробовать этот запрос:
--you are getting NumberGroup (using window function )
with cte as
(
select *, sum(ID)over(order by Row rows unbounded preceding)NumGr from Table
)
-- using FOR XML PATH to get one row within group (Full text in your case)
select min(Row)Row,
max(ID)ID,max(Name)Name,max(Notes_new)Notes
from
(
select *, stuff((select ' ' Notes from cte cte1 where cte1.NumGr=cte2.NumGr
FOR XML PATH('')),1,1,'')Notes_new
from cte cte2
)X
group by NumGr