Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Преобразование одного xml в другой вид xml / 14 сообщений из 14, страница 1 из 1
14.10.2020, 11:21
    #40008373
mih.dim1
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
Добрый день. Подскажите как сделать это быстро в плане производительности при помощи xml команд MS SQL (Xquery) или может чего то еще, но именно в MS SQL без подключения сторонних библиотек и т.п.
Есть таблица с 500 тыс. записей. в ней есть поле типа xml следующего вида:
<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value1>
<number>32424244</number>
<value3>5</value1>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value1>
<value3>10</value1>
</data>

И нее нужно получить "правильную" xml:
<data>
<row>
<number>17345665</number>
</row>
<row>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
</row>
<row>
<value1>1</value1>
<value2>2</value1>
</row>
<row>
<number>32424244</number>
<value3>5</value1>
</row>
<row>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value1>
<value3>10</value1>
</row>
</data>


Известно что
1.Тэги name и number всегда идут раньше чем value1-3
2. name, number, value1-3 - это все тэги которые могут быть
3. Любого элемента может не быть

По сути нужно разбить по строчно записи. Парсинг через строку медленно работает. Можете предложить решение или хотя бы направление дать через что идти. Спасибо
...
Рейтинг: 0 / 0
14.10.2020, 12:43
    #40008404
Konst_One
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
может через преобразование xsl попробуете?
...
Рейтинг: 0 / 0
14.10.2020, 13:35
    #40008429
Dimbuch®
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
...
Рейтинг: 0 / 0
14.10.2020, 13:49
    #40008436
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
mih.dim1,

в общем случае порядок элементов не имеет значения. Например, если такой документ загрузить в DOM, то в свойстве XML вы получите другой порядок строк.

OPENXML имеет внутренний нумератор строк, которым можно было бы воспользоваться, но я не знаю - поможет ли он как-то при разборе, не будут ли перестановки. Гарантий нет, в общем-то.
...
Рейтинг: 0 / 0
14.10.2020, 13:58
    #40008441
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
Владислав Колосов
mih.dim1,

в общем случае порядок элементов не имеет значения. Например, если такой документ загрузить в DOM, то в свойстве XML вы получите другой порядок строк.

OPENXML имеет внутренний нумератор строк, которым можно было бы воспользоваться, но я не знаю - поможет ли он как-то при разборе, не будут ли перестановки. Гарантий нет, в общем-то.


Поскольку это не XML, а бред. То работать с ним надо как с бредом.

REPLACE, STRING_SPLIT спасут отца русской демократии.
...
Рейтинг: 0 / 0
14.10.2020, 14:12
    #40008449
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
mih.dim1
<value3>10</value1>

Где здесь xml ?
...
Рейтинг: 0 / 0
14.10.2020, 14:28
    #40008455
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
env,

да ладно вам, в целом понятно чего хочет добиться ТС. полагаю что он там накосячил с закрытием тэгов (очень похоже на копипаст).

задача в целом геморная:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<data>
    <!--группа 1-->
    <number>17345665</number>
    <!--группа 2-->
    <number>19429405</number>
       <name>Тест1</name>
       <value1>84</value1>
    <!--группа 3-->
    <number>11024248</number>
        <value1>1</value1>
        <value2>2</value2>
     <!--группа 4-->
     <number>32424244</number>
        <value3>5</value1>
     <!--группа 5-->
     <name>Тест2</name>
         <value1>6</value1>
         <value2>8</value2>
         <value3>10</value3>
</data>



ему нужно разбить этот свой xml на список элементов и сгруппировать их по порядку вхождения элементов, при этом каждый раз начинать новую группу если вчтречается элемент который ранее уже был сгруппирован.

на вскидку это будет чето типа
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
declare @x xml = '<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value2>
<number>32424244</number>
<value3>5</value3>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value2>
<value3>10</value3>
</data>'

declare @tbl table (id int, val varchar(max));
declare @knownTags table (val varchar(255));

insert into @knownTags values ('<number>'), ('<name>'), ('<value1>'), ('<value2>'), ('<value3>')

insert into @tbl 
select row_number() over (order by 1/0) -1 as [rn], cast(T.c.query('.') as varchar(max)) from @x.nodes('//*')T(c) order by 1 offset 1 row



а потом начинать шаманить с оконками в плане создания групп, повидимому какие то безумные CASE.
возможно при такой ломанной логике "новой группы" легче сделать итерационно через while / cursor;

написал только для задания вектора

над гемморной задачей что то напрягаться не хочется :)
...
Рейтинг: 0 / 0
14.10.2020, 14:35
    #40008459
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
Это цирк просто. Надо написать приложение, причем довольно примитивное, которое добавит нужные строки.

Загружаем строку из таблицы, парсим в массив и цикл по массиву строк с проверкой ключевых слов для вставки <row>.
...
Рейтинг: 0 / 0
14.10.2020, 15:00
    #40008477
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
mih.dim1,

Можно как-то так
Код: 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.
declare @s varchar(max) = '<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value2>
<number>32424244</number>
<value3>5</value3>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value2>
<value3>10</value3>
</data>';

with a as
(
 select
  row_number() over (order by d.n) as rn,
  e.s,
  case
   when e.s like '<number>%' then 1
   when e.s like '<name>%' and lag(e.s) over (order by d.n) not like '<number>%' then 1
   else 0
  end as f
 from
  (select replace(replace(@s, '<data>', ''), '</data>', '')) a(s) cross apply
  (select cast(cast('' as xml).query('sql:column("a.s")') as varchar(max))) b(s) cross apply
  (select cast('<part>' + replace(replace(b.s, char(13), ''), char(10), '</part><part>') + '</part>' as xml)) c(x) cross apply
  c.x.nodes('/part') d(n) cross apply
  (select d.n.value('.', 'varchar(max)')) e(s)
 where
  e.s > '<'
),
b as
(
 select *, sum(f) over (order by rn) as g from a
)
select
 cast(string_agg(s, '') within group (order by rn) as xml)--as [row]
from
 b
group by
 g
for xml path('row');
...
Рейтинг: 0 / 0
14.10.2020, 16:28
    #40008538
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
Код: 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.
declare @xml xml ='
<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value2>
<number>32424244</number>
<value3>5</value3>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value2>
<value3>10</value3>
</data>'

;with cte as (
	select
		row_number()over(order by (select 1)) as tag_num
		,t.c.value('local-name(.)', 'varchar(50)') as tag_name
		,t.c.value('./text()[1]', 'varchar(20)') as tag_value
		,lag(t.c.value('local-name(.)', 'varchar(50)'))over(order by (select 1)) as tag_prev
	from @xml.nodes('data/*') as t(c)
),
cte1 as (
	select
		*
		,case when (tag_name = 'number' and isnull(tag_prev,'') <> 'name') or (tag_name = 'name' and isnull(tag_prev,'') <> 'number') then 1 else 0 end as grp_flag
	from cte
),
cte2 as (
	select  
		*
		,sum(grp_flag)over(order by tag_num) as grp_num
	from cte1
)
select
	/*grp_num,*/ [name], [number], [value1], [value2], [value3]
from (select tag_name, tag_value, grp_num from cte2) t
pivot (max(tag_value) for tag_name in ([name], [number], [value1], [value2], [value3])) as pvt 
for xml raw, elements


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
<row>
  <number>17345665</number>
</row>
<row>
  <name>Тест1</name>
  <number>19429405</number>
  <value1>84</value1>
</row>
<row>
  <number>11024248</number>
  <value1>1</value1>
  <value2>2</value2>
</row>
<row>
  <number>32424244</number>
  <value3>5</value3>
</row>
<row>
  <name>Тест2</name>
  <value1>6</value1>
  <value2>8</value2>
  <value3>10</value3>
</row>
...
Рейтинг: 0 / 0
15.10.2020, 00:36
    #40008673
mih.dim1
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
env
mih.dim1
<value3>10</value1>

Где здесь xml ?


Извеняйте моя опечатка.
...
Рейтинг: 0 / 0
15.10.2020, 00:38
    #40008674
mih.dim1
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
mih.dim1,
Всем спасибо за информацию и оперативные ответы. Сейчас переключили на другую работу, но скоро проверю предложенные варианты и сообщу результат. Пока написал тупой парсинг строк в цикле. За 20 мин отработал. Но ваши варианты куда интереснее. Буду смотреть.
...
Рейтинг: 0 / 0
15.10.2020, 17:34
    #40009002
HandKot
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
mih.dim1,

мне кажется лучше обычным реплейсом

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
declare @xml nvarchar(max) = N'
<data>
 <number>17345665</number>
 <number>19429405</number>
 <name>Тест1</name>
 <value1>84</value1>
 <number>11024248</number>
 <value1>1</value1>
 <value2>2</value2>
 <number>32424244</number>
 <value3>5</value3>
 <name>Тест2</name>
 <value1>6</value1>
 <value2>8</value2>
 <value3>10</value3>
</data>'

Select
	Cast(Replace(Replace(Replace(@xml, N'<data>', N'<data><row>'), N'<number>', N'</row><row><number>'), '</data>', '</row></data>') As Xml)



Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
<data>
  <row />
  <row>
    <number>17345665</number>
  </row>
  <row>
    <number>19429405</number>
    <name>Тест1</name>
    <value1>84</value1>
  </row>
  <row>
    <number>11024248</number>
    <value1>1</value1>
    <value2>2</value2>
  </row>
  <row>
    <number>32424244</number>
    <value3>5</value3>
    <name>Тест2</name>
    <value1>6</value1>
    <value2>8</value2>
    <value3>10</value3>
  </row>
</data>


лишний тэг "роу", можно потом прибить, если надо
...
Рейтинг: 0 / 0
15.10.2020, 18:01
    #40009018
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Преобразование одного xml в другой вид xml
HandKot

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
<data>
  <row />
  <row>
    <number>17345665</number>
  </row>
  <row>
    <number>19429405</number>
    <name>Тест1</name>
    <value1>84</value1>
  </row>
  <row>
    <number>11024248</number>
    <value1>1</value1>
    <value2>2</value2>
  </row>
  <row>
    <number>32424244</number>
    <value3>5</value3>
    <name>Тест2</name>
    <value1>6</value1>
    <value2>8</value2>
    <value3>10</value3>
  </row>
</data>



лишний тэг "роу", можно потом прибить, если надо
Этот name и valueХ ниже, по ТЗ, ещё одна группа
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Преобразование одного xml в другой вид xml / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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