Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите преобразовать EAV таблицу в хмл / 7 сообщений из 7, страница 1 из 1
14.02.2019, 14:17
    #39773857
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
Коллеги приветствую!
Помогите преобразовать в хмл произвольную 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
14.02.2019, 18:47
    #39774037
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
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
14.02.2019, 18:48
    #39774039
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
понятное дело что все эти multiple-replace это костыль, думаю можно сделать так что бы не прописывать вручную
...
Рейтинг: 0 / 0
14.02.2019, 19:21
    #39774063
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
Код: 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
15.02.2019, 16:11
    #39774629
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
court, бесподобно!
Большое спасибо. Именно то, что надо.
...
Рейтинг: 0 / 0
15.02.2019, 16:12
    #39774631
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
felix_ff, на первый взгляд - это не то, т.к. названия тегов - могут быть абсолютно любые, и их не захардкодишь в запросе.
Однако, попытаюсь вкурить.
Спасибо.
...
Рейтинг: 0 / 0
15.02.2019, 16:41
    #39774653
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите преобразовать EAV таблицу в хмл
uaggster,

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

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


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