powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите преобразовать EAV таблицу в хмл
7 сообщений из 7, страница 1 из 1
Помогите преобразовать EAV таблицу в хмл
    #39773857
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги приветствую!
Помогите преобразовать в хмл произвольную EAV таблицу:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
if OBJECT_ID('tempdb..#eav') is not Null
	drop table #eav

Create table #eav ([id] nvarchar(100), [field] nvarchar(100), [value] nvarchar(100))

insert into #eav
	Values   ('0001', 'root1', Null)
			,('0001/0001', 'fiel1', '1')
			,('0001/0002', 'fiel2', '2')
			,('0001/0002/0001', 'fiel3', '3')
			,('0001/0002/0001/0001', 'fiel5', '5')
			,('0001/0002/0002', 'fiel4', '4')


На выходе должен получиться вот такой xml:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
<root>
  <field1>1</field1>
  <field2>
    <field3>
      <field5>5</field5>
3</field3>
    <field4>4</field4>
2</field2>
</root>


Дада, mixed content, и всё такое.
Значение поля [field], в общем случае - произвольное!

Решаема ли такая задача средствами TSQL?
Мне кажется, что не решаема.
Но тогда, может быть, есть возможность что-то добавить в #eav, чтобы она стала решаемой?

Кстати, совершенно необязательно использовать один запрос. Можно динамический sql, или временные таблицы.
Хотелось бы избежать только курсора.
Хотя, если нет другого выхода...
...
Рейтинг: 0 / 0
Помогите преобразовать EAV таблицу в хмл
    #39774037
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
drop table if exists #eav, #tmp, #tmp2;
Create table #eav ([id] nvarchar(100), [field] nvarchar(100), [value] nvarchar(100))

insert into #eav
	Values   ('0001', 'root1', Null)
			,('0001/0001', 'field1', '1')
			,('0001/0002', 'field2', '2')
			,('0001/0002/0001', 'field3', '3')
			,('0001/0002/0001/0001', 'field5', '5')
			,('0001/0002/0002', 'field4', '4');

update tmp
   set [id] = '/'+xx.val
  from #eav tmp
      cross apply (select x.data.value('.', 'varchar(max)') from (select cast(cast(t.value as int) as varchar) + '/' from string_split(tmp.id, '/') t for xml path(''), type) x(data)) xx (val);

select cast(id as hierarchyid) as rid, cast(id as hierarchyid).GetAncestor(1) as parentid, * into #tmp from #eav;

alter table #tmp add [rowid] int identity(1,1);


declare @fieldlist varchar(max) = '';
select @fieldlist = @fieldlist + '{val' + cast([rowid] as varchar) + '} as ' + quotename([field]+'!'+cast([rowid] as varchar)+'!') + ', ' from #tmp

select
      iif(t.[rowid] = 1, 'select ', ' union all select ') + cast(t.[rowid] as varchar) +' as [Tag], ' + isnull(cast(p.[rowid] as varchar), 'NULL') +' as [Parent], ' + replace(@fieldlist, '{val' + cast(t.[rowid] as varchar)+'}', isnull(t.value, 'NULL')) as [stmt]
      into #tmp2
from #tmp t
    outer apply (select t2.rowid from #tmp t2 where t2.rid = t.parentid) p;
    
declare @sql varchar(max) = '';
with x (data) as (
    select replace(replace(replace(replace(replace(replace(left(stmt, len(stmt)-1), '{val1}', 'NULL'), '{val2}', 'NULL'), '{val3}', 'NULL'), '{val4}', 'NULL'), '{val5}', 'NULL'), '{val6}', 'NULL')
    from #tmp2 for xml path(''), type
) 
select @sql = data.value('.', 'varchar(max)')
from x;

set @sql += ' for xml explicit';

exec (@sql);



В ближайшем рассмотрении что то типа того для версии >= 2016
...
Рейтинг: 0 / 0
Помогите преобразовать EAV таблицу в хмл
    #39774039
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
понятное дело что все эти multiple-replace это костыль, думаю можно сделать так что бы не прописывать вручную
...
Рейтинг: 0 / 0
Помогите преобразовать EAV таблицу в хмл
    #39774063
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
if OBJECT_ID('tempdb..#eav') is not Null
	drop table #eav

Create table #eav ([id] nvarchar(100), [field] nvarchar(100), [value] nvarchar(100))

insert into #eav
	Values   ('0001', 'root1', null)
			,('0001/0001', 'fiel1', '1')
			,('0001/0002', 'fiel2', '2')
			,('0001/0002/0001', 'fiel3', '3')
			,('0001/0002/0001/0001', 'fiel5', '5')
			,('0001/0002/0002', 'fiel4', '4')

--	***********************
declare @SQL nvarchar(max)
declare @xml xml

;with cte as (
	select
		[id] 
		,[path]	=cast([field] as varchar(max))
		,lvl	=0
		,[value]
	 from #eav
	 where [id] not like '%/%'

	 union all

	select
		t.[id] 
		,[path]	=cte.[path]+'/'+cast([field] as varchar(max))
		,lvl	=cte.lvl+1
		,t.[value]
	 from #eav t inner join cte on t.id like cte.id+'/%'
	 where len(t.[id])-len(replace(t.[id],'/','')) = cte.lvl+1
)
--select * from cte 

select @SQL=(select ''''+[value]+''' as ['+[path]+'], ' from cte order by [path], lvl for xml path(''))

--print @SQL
set @SQL =N'set @xml=(select '+left(@SQL,len(@SQL)-1)+' for xml path(''''),elements)' 
--print @SQL

--
exec sp_executesql @SQL, N'@xml xml out', @xml=@xml out 

select @xml 
/*
<root1>
	<fiel1>1</fiel1>
	<fiel2>2
		<fiel3>3
			<fiel5>5</fiel5>
		</fiel3>
		<fiel4>4</fiel4>
	</fiel2>
</root1>
*/
...
Рейтинг: 0 / 0
Помогите преобразовать EAV таблицу в хмл
    #39774629
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
court, бесподобно!
Большое спасибо. Именно то, что надо.
...
Рейтинг: 0 / 0
Помогите преобразовать EAV таблицу в хмл
    #39774631
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff, на первый взгляд - это не то, т.к. названия тегов - могут быть абсолютно любые, и их не захардкодишь в запросе.
Однако, попытаюсь вкурить.
Спасибо.
...
Рейтинг: 0 / 0
Помогите преобразовать EAV таблицу в хмл
    #39774653
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

по сути идея та же: получить иерархию предок-потомок и потом завернуть в правльный for xml.

только я чет не додумался до создания полей для path, а пошел методом создания таблицы для for xml explicit что накладывает жутко неудобные конструкции именования полей.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите преобразовать EAV таблицу в хмл
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]