#sql #sql-server #sql-server-2008-r2
#sql #sql-сервер #sql-server-2008-r2
Вопрос:
Я работаю с инструкциями SQL Server и имею одну таблицу, подобную:
| item | value | parentItem |
------ ------- ------------
| 1 | 2test | 2 |
| 2 | 3test | 3 |
| 3 | 4test | 4 |
| 5 | 1test | 1 |
| 6 | 3test | 3 |
| 7 | 2test | 2 |
И я хотел бы получить приведенный ниже результат, используя инструкцию SQL Server:
| item1 | value1 |
------- --------------------------
| 1 | /4test/3test/2test |
| 2 | /4test/3test |
| 3 | /4test |
| 5 | /4test/3test/2test/1test |
| 6 | /4test/3test |
| 7 | /4test/3test/2test |
Я не нашел правильного SQL для получения всех значений для всех идентификаторов в соответствии с parentItem.
Я пробовал этот SQL :
with all_path as
(
select item, value, parentItem
from table
union all
select a.item, a.value, a.parentItem
from table a, all_path b
where a.item = b.parentItem
)
select
item as item1,
stuff(select '/' value
from all_path
order by item asc
for xml path ('')), 1, 0, '') as value1
from
all_path
Но получил столбец «value1» в результате, подобный
/4test/4test/4test/3test/3test/3test/3test/2test/2test/2test/2test
Не могли бы вы, пожалуйста, помочь мне с этим? Большое спасибо.
Комментарии:
1. Вы просто хотите это в качестве выходных данных? Или вы хотите изменить данные в таблице на другую структуру? Я не думаю, что вам нужно
MERGE
в любом случае, что вы пробовали?2. Спасибо за вопросы. Я обновил вопросы. Не могли бы вы, пожалуйста, помочь проверить это?
3. SQL Server 2008 R2
4. Хорошо, особенно при использовании устаревшей и больше не поддерживаемой версии, всегда полезно пометить ее заранее, потому что люди, как правило, ожидают более новые версии (где решение может быть другим / лучше).
5. Привет @AnneLiu, отличная работа!. Мое решение, приведенное ниже, очень похоже. Я думаю, вам не хватает GROUP BY при окончательном выборе
Ответ №1:
основываясь на полученном вами ожидаемом результате, используйте рекурсивную часть для объединения значения
;with yourTable as (
select item, value, parentItem
from (values
(1,'2test',2)
,(2,'3test',3)
,(3,'4test',4)
,(5,'1test',1)
,(6,'3test',3)
,(7,'2test',2)
)x (item,value,parentItem)
)
, DoRecursivePart as (
select 1 as Pos, item, convert(varchar(max),value) value, parentItem
from yourTable
union all
select drp.pos 1, drp.item, convert(varchar(max), yt.value '/' drp.value), yt.parentItem
from yourTable yt
inner join DoRecursivePart drp on drp.parentItem = yt.item
)
select drp.item, '/' drp.value
from DoRecursivePart drp
inner join (select item, max(pos) mpos
from DoRecursivePart
group by item) [filter] on [filter].item = drp.item and [filter].mpos = drp.Pos
order by item
дает
item value
----------- ------------------
1 /4test/3test/2test
2 /4test/3test
3 /4test
5 /4test/3test/2test/1test
6 /4test/3test
7 /4test/3test/2test
Ответ №2:
Вот пример данных
drop table if exists dbo.test_table;
go
create table dbo.test_table(
item int not null,
[value] varchar(100) not null,
parentItem int not null);
insert dbo.test_table values
(1,'test1',2),
(2,'test2',3),
(3,'test3',4),
(5,'test4',1),
(6,'test5',3),
(7,'test6',2);
Вот запрос
;with recur_cte(item, [value], parentItem, h_level) as (
select item, [value], parentItem, 1
from dbo.test_table tt
union all
select rc.item, tt.[value], tt.parentItem, rc.h_level 1
from dbo.test_table tt join recur_cte rc on tt.item=rc.parentItem)
select rc.item,
stuff((select '/' cast(parentItem as varchar)
from recur_cte c2
where rc.item = c2.item
order by h_level desc FOR XML PATH('')), 1, 1, '') [value1]
from recur_cte rc
group by item;
Вот результаты
item value1
1 4/3/2
2 4/3
3 4
5 4/3/2/1
6 4/3
7 4/3/2
Комментарии:
1. string_agg не поддерживается в sql server 2008