Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
Есть таблица: [uid, name, parentUid]. В ней соответственно родительские строчки с parentUid is NULL. У детей соответственно parentUid равный uid'у родителя. У одного родителя несколько детей. Мне надо возвратить XML'ник вида:

<group id="3FD06F1B-A5AA-4F69-9BAD-59CEA8A4C9FD" name="ИМЯ">
    <valueYear ftid="10" value=""/>
    <valuePeriod ftid="20" value=""/>
    <value ftid="30" value=""/>
</group>
<group id="3FD66F1B-A5AA-4F69-9BAD-59CEA8A4C9FD" name="ИМЯ">
    <valueYear ftid="10" value=""/>
    <valuePeriod ftid="20" value=""/>
    <value ftid="30" value=""/>
</group>
...


Запрос строю, что-то вроде этого:
SELECT
p.[uid] as id,
p.code as name,
p.name as fullName,
(
select
(select parent.uid from dbo.groups as parent where parent.uid = g.parentUid) as id,
p.name as income, p.code as code, p.code as name,
(select '10' as ftid, '' as value
From (select 1 as a) as "valueYear"
For XML auto, type),
(select '20' as ftid, '' as value
From (select 1 as a) as "valuePeriod"
For XML auto, type),
(select '30' as ftid, '' as value
From (select 1 as a) as "value"
For XML auto, type)
From (select 1 as a) as "group"
For XML auto) as xml,

ROW_NUMBER()
OVER (ORDER BY code) AS rnum
FROM dbo.income p INNER JOIN groups g ON p.uid=g.uid

Но у меня получается только 1 тег group с подтегами. И с другим id.
Подскажите, плиз, как сделать такое количество тегов group сколько детей есть у определённого uid'а. Надеюсь, понятно объяснил проблему.
11 апр 13, 13:07    [14166731]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
denis2710
Member

Откуда: Москва
Сообщений: 3384
Xape4ka, не совсем понятно о чем речь
+ ну на пример

declare @t table ( uid int ,name varchar ( 50 ) ,parentUid int )
insert into @t
  (
    uid
   ,name
   ,parentUid
  )
values
  (
    1
   ,'paren1'
   ,null
  )
, ( 2 ,'paren2' ,null )
, ( 3 ,'chil3' ,1 )
, ( 4 ,'chil4' ,1 )
, ( 5 ,'chil5' ,2 )
, ( 6 ,'chil6' ,2 )
select parent.uid
      ,parent.name
      ,parent.parentUid
      ,child.uid
      ,child.name
      ,child.parentUid
      ,row_number() 
       over ( order by child.parentUid )  as cnum
from   @t parent
inner join @t child on  child.parentUid = parent.uid
     for xml auto;

11 апр 13, 13:51    [14167025]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
denis2710
не совсем понятно о чем речь

Вот тот запрос который я привёл в начале темы, это часть процедуры селектора. Мне нужно сделать так, чтобы в селекторе я выбирал родительский код, а он мне возвращал XML того вида, что я привёл, где каждый элемент "group" является child'ом выбираемого. То есть у меня загвоздка именyо во втором селекте, который делает XML, соответственно "p.[uid] as id," у меня это родительский UID.
11 апр 13, 15:46    [14167922]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
denis2710
Member

Откуда: Москва
Сообщений: 3384
Xape4ka,
+ Так что ли?

declare @groups table ( uid int ,parentUid int )
insert into @groups
  (
    uid
   ,parentUid
  )
values
  (
    1
   ,3
  ), ( 2 ,1 )
declare @income table ( uid int ,code varchar ( 50 ) ,name varchar ( 50 ) )
insert into @income
  (
    uid
   ,code
   ,name
  )
values
  (
    1
   ,'xxx'
   ,'name155'
  )
, ( 1 ,'xxx11' ,'name1' )
, ( 1 ,'xxx1' ,'name12223223' )
, ( 2 ,'xxx222' ,'name12222' )
, ( 2 ,'xxx2222' ,'name1333' )


select p.[uid]                 as id
      ,p.code                  as name
      ,p.name                  as fullName
      ,(
           select g.parentUid   as Id
                 ,"group".name  as income
                 ,"group".code  as code
                 ,"group".code  as name
                 ,(
                      select '10'  as     ftid
                            ,''  as       value
                      from   (
                                 select 1  as a
                             )         as "valueYear"
                             for xml auto
                            ,type
                  )
                 ,(
                      select '20'  as     ftid
                            ,''  as       value
                      from   (
                                 select 1  as a
                             )         as "valuePeriod"
                             for xml auto
                            ,type
                  )
                 ,(
                      select '30'  as     ftid
                            ,''  as       value
                      from   (
                                 select 1  as a
                             )         as "value"
                             for xml auto
                            ,type
                  )
           from   @income       as "group"
           where  "group".uid = p.uid
                  for xml auto,type
       )                       as ver1
      ,(
           select g.parentUid  as id
                 ,p.name       as income
                 ,p.code       as code
                 ,p.code       as name
                 ,(
                      select '10'  as     ftid
                            ,''  as       value
                      from   (
                                 select 1  as a
                             )         as "valueYear"
                             for xml auto
                            ,type
                  )
                 ,(
                      select '20'  as     ftid
                            ,''  as       value
                      from   (
                                 select 1  as a
                             )         as "valuePeriod"
                             for xml auto
                            ,type
                  )
                 ,(
                      select '30'  as     ftid
                            ,''  as       value
                      from   (
                                 select 1  as a
                             )         as "value"
                             for xml auto
                            ,type
                  )
           from   (
                      select 1  as a
                  )            as "group"
                  for xml auto
                 ,type
       )                       as OldVer
      ,row_number() 
       over ( order by code )  as rnum
from   @income p
inner join @groups g on  p.uid = g.uid

11 апр 13, 17:27    [14168680]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
В общем для наглядности того что мне надо, вот картинка

Картинка с другого сайта.

Эта таблица результат вот этого запроса:
+
         SELECT 
            p.[uid] as id,
            p.code as name,
            p.name as fullName,
            (
            select 
			   p.uid as id,
				 p.code as code, p.code as name,
			  (select '10' as ftid, '' as value
			  From (select 1 as a)  as "valueYear"
			  For XML auto, type),
			  (select '20' as ftid, '' as value
			  From (select 1 as a)  as "valuePeriod"
			  For XML auto, type),
			  (select '30' as ftid, '' as value
			  From (select 1 as a)  as "value"
			  For XML auto, type)
			 From (select 1 as a) "group" 
			 where p.uid in (select parentUid from groups)
			 For XML auto
			 ) as temp,
			 
            ROW_NUMBER() 
            OVER (ORDER BY code) AS rnum 
         FROM dbo.Income p INNER JOIN groups g ON p.uid=g.uid


Первый элемент родительский, остальные его дети, надо чтобы у него в ячейку temp возвращался xml вида
<group id="BF4455D9-FC2D-47F6-850A-AD2306592391" name="ИМЯ">
    <valueYear ftid="10" value=""/>
    <valuePeriod ftid="20" value=""/>
    <value ftid="30" value=""/>
</group>
<group id="00DB3E57-B264-44C8-B30C-77C01EFDDD40" name="ИМЯ">
    <valueYear ftid="10" value=""/>
    <valuePeriod ftid="20" value=""/>
    <value ftid="30" value=""/>
</group>
...

Количество элементов GROUP, чтобы равнялось количеству детей.
11 апр 13, 17:38    [14168762]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
denis2710
Xape4ka,
Так что ли?

Сейчас проверю.
11 апр 13, 17:38    [14168766]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
denis2710,

Нет. Не так к сожалению, такое решение я уже и сам делал) Посмотрите, я привёл пример с картинками как надо. Вроде не так сложно, но что-то я затупил, видать сказывается окончание недели.
11 апр 13, 17:51    [14168854]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Glory
Member

Откуда:
Сообщений: 104751
Уровень вложенности вашего дерева 1 или много ?
11 апр 13, 17:56    [14168890]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
Glory,

Один, если я конечно правильно понял, что вы имеете ввиду)
11 апр 13, 18:00    [14168907]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Glory
Member

Откуда:
Сообщений: 104751
auto - это обязательное условие при написании запроса ?
11 апр 13, 18:03    [14168930]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
Glory,

Нет, мне просто надо создать XML'ник. Да, новерно стоило тему немного по другому назвать.
11 апр 13, 18:07    [14168947]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Glory
Member

Откуда:
Сообщений: 104751
Тогда предложу FOR XML EXPLICIT
UNION двух запросов - в 1ом - родители, во 2ом - дети
11 апр 13, 18:14    [14168979]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
Glory,

Да так мне же не нужны родители в результирующем XML, мне надо, чтобы XML с детьми записывался в поле TEMP к родителю.
11 апр 13, 19:13    [14169262]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3449
Как-то вы очень путано объясняете. Лучше привести пример данных БЕЗ картинок, и что нужно получить.
Xape4ka
Эта таблица результат вот этого запроса:
И чем же плох ваш запрос? Вроде бы он делает все то, что нужно вам.
12 апр 13, 08:37    [14170757]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
Ennor Tiegael,

У меня на картинке в поле TEMP вот такой XML:
<group id="3FD05F1B-A5AA-4F69-9BAD-59CEA8A4C9FD" code="КОД" name="ИМЯ"><valueYear ftid="10" value=""/><valuePeriod ftid="20" value=""/><value ftid="30" value=""/></group>


Как видите атрибут id равен uid родителя. А мне надо чтобы атрибут id был равен uid ребёнка этого родителя и соответственно количество элементов "group" было равно количеству детей у этого родителя. То есть, вот так:
<group id="BF4455D9-FC2D-47F6-850A-AD2306592391" code="КОД_1ребёнка" name="ИМЯ_1ребёнка"><valueYear ftid="10" value=""/><valuePeriod ftid="20" value=""/><value ftid="30" value=""/></group>
<group id="00DB3E57-B264-44C8-B30C-77C01EFDDD40" code="КОД_2ребёнка" name="ИМЯ_2ребёнка"><valueYear ftid="10" value=""/><valuePeriod ftid="20" value=""/><value ftid="30" value=""/></group>
<group id="5801E09F-B57A-4AA4-9E89-F60EEA063D44" code="КОД_3ребёнка" name="ИМЯ_3ребёнка"><valueYear ftid="10" value=""/><valuePeriod ftid="20" value=""/><value ftid="30" value=""/></group>
...
И т.д.
12 апр 13, 10:29    [14171228]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Xape4ka
Member

Откуда:
Сообщений: 34
Xape4ka,

Нашли с коллегой решение. Немного мозговынос правда. Но может быть кому-нибудь будет полезно.
         SELECT 
            Income1.[uid] as id,
            Income1.code as name,
            Income1.name as fullName,
            
            cast((SELECT(
						select 
						   "group".uid as id,
							 (select code from svod..Income where Income.uid="group".uid) as code
							 , (select code from svod..Income where Income.uid="group".uid) as name,
							 coalesce(cast("group".parentUid as varchar(50)), '') as parent,
						  (select '10' as ftid, '' as value
						  From (select 1 as a)  as "valueYear"
						  For XML auto, type),
						  (select '20' as ftid, '' as value
						  From (select 1 as a)  as "valuePeriod"
						  For XML auto, type),
						  (select '30' as ftid, '' as value
						  From (select 1 as a)  as "value"
						  For XML auto, type)
						 From SVOD.dbo.groups "group"
						 where [group].uid = groups.uid OR
								[group].parentUid = groups.uid
						 order by groups.parentUid, groups.sort

						 For XML auto, type
						 )
					 from  svod.dbo.groups groups 
						  INNER JOIN svod.dbo.Income Income
						  ON Income.uid=groups.uid
						   
					where Income.uid =Income1.uid
					 for XML auto) as xml) as temp,
			 
            ROW_NUMBER() 
            OVER (ORDER BY code) AS rnum 
         FROM svod.dbo.Income Income1
          INNER JOIN svod.dbo.groups groups1 
				ON Income1.uid=groups1.uid

В результате данного запроса возвращается в поле TEMP к родительскому элементу XML такого вида:
<groups>
  <group id="DDAA0791-AE6D-4870-BC40-3003AC3CD3CE" code="КОД_1ребёнка" name="Имя_1ребёнка" parent="3FD05F1B-A5AA-4F69-9BAD-59CEA8A4C9FD">
    <valueYear ftid="10" value="" />
    <valuePeriod ftid="20" value="" />
    <value ftid="30" value="" />
  </group>
...
...
...
  <group id="5801E09F-B57A-4AA4-9E89-F60EEA063D44" code="КОД_Nребёнка" name="Имя_Nребёнка" parent="3FD05F1B-A5AA-4F69-9BAD-59CEA8A4C9FD">
    <valueYear ftid="10" value="" />
    <valuePeriod ftid="20" value="" />
    <value ftid="30" value="" />
  </group>
</groups>

Каждому ребёнку вот такой:
<groups>
  <group id="BF4455D9-FC2D-47F6-850A-AD2306592391" code="КОД данного ребёнка" name="Имя данного ребёнка" parent="3FD05F1B-A5AA-4F69-9BAD-59CEA8A4C9FD">
    <valueYear ftid="10" value="" />
    <valuePeriod ftid="20" value="" />
    <value ftid="30" value="" />
  </group>
</groups>
12 апр 13, 17:25    [14174482]     Ответить | Цитировать Сообщить модератору
 Re: Помогите спарсить XML при помощи "For XML auto"  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3449
Xape4ka,

Пипец вы наворотили. Куча лишних джойнов, опасно совпадающие алиасы таблиц на разных уровнях... Но зато главное условие выполнено, да - все на FOR XML AUTO.

Откройте для себя дао, что ли:
-- Пример данных и его заполнение
declare @parent table (
	Id uniqueidentifier primary key default newid(),
	Code sysname not null
);

insert into @parent (Code)
values ('Name'), ('Surname'), ('Patronymic'), ('Empty');

declare @child table (
	Id uniqueidentifier primary key default newid(),
	ParentId uniqueidentifier not null,
	ValueYear int not null,
	Value int not null
);

insert into @child (ParentId, ValueYear, Value)
select sq.Id, ca.ValueYear, ca.Value
from (
	select Id, Code, row_number() over(order by code) % 4 as [rn]
	from @parent p
	) sq
	cross apply (
		select top (sq.rn) v.number as [ValueYear], v.low as [Value]
		from master.dbo.spt_values v
		where v.type = 'P'
		order by newid()
	) ca;

-- Собственно запрос
select p.Id, p.Code, (
	select c.Id as [Group/@Id], c.ValueYear as [Group/ValueYear/@Value], c.Value as [Group/Value/@Value]
	from @child c
	where c.ParentId = p.Id
	order by c.Value
	for xml path(''), type, root('Groups')
	) as [temp], row_number() over(order by p.code) as [rnum]
from @parent p;

Я не знаю, такая у вас структура таблиц или нет - вы отказались ее привести. Тем хуже для вас.
Версию, впрочем, вы тоже не озвучили, так что заранее предупреждаю, что на 2000 и более ранних не взлетит.
12 апр 13, 21:15    [14175271]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить