Присоединяйтесь к XML столбцам из SQL Server 2016+ - PullRequest
0 голосов
/ 06 мая 2020

У меня есть TABLE_A со столбцом XML mycategoryXML, который содержит это XML:

<mainxml>
     <category id="1" ftype="1"/>
     <category id="2" ftype="1"/>
     <category id="3" ftype="1"/>
</mainxml>

У меня также есть другой TABLE_B со столбцом XML под названием mymappedids

<mapids>
    <ids>
        <myid id="1" name="Category Name1"/>
        <myid id="2" name="Category Name2"/>
        <myid id="3" name="Category Name3"/>
        <myid id="4" name="Category Name4"/>
        <myid id="5" name="Category Name5"/>
        <myid id="6" name="Category Name6"/>
        <myid id="7" name="Category Name7"/>
        <myid id="8" name="Category Name8"/>
        <myid id="9" name="Category Name9"/>
    </ids>
</mapids>

Можно ли выбрать все Category узлы из TABLE_A, а также правильные имена для каждой категории из table_B, поэтому я в конечном итоге получаю следующий результат:

      id | categoryid | categoryname
      ---+------------+-------------
      1  |    1       | categoryname1
      2  |    2       | categoryname2
      3  |    3       | categoryname3

с одним запросом от SQL Сервера?

Ответы [ 2 ]

3 голосов
/ 06 мая 2020

Есть несколько подходов, но вы недостаточно рассказали нам о своей биографии.

Особенно неясно: какова связь между этими двумя таблицами a и b?

Вы можете попробовать что-нибудь вместе это:

A сценарий макета для имитации вашей проблемы (укажите это сами в следующем вопросе):

DECLARE @tblA TABLE(aId INT,Xml1 XML);
DECLARE @tblB TABLE(bId INT,Xml2 XML);

INSERT INTO @tblA(aId,Xml1) VALUES
(100
,N'<mainxml>
     <category id="1" ftype="1"/>
     <category id="2" ftype="1"/>
     <category id="3" ftype="1"/>
</mainxml>');
INSERT INTO @tblB(bId,Xml2) VALUES
(200
,N'<mapids>
    <ids>
        <myid id="1" name="Category Name1"/>
        <myid id="2" name="Category Name2"/>
        <myid id="3" name="Category Name3"/>
        <myid id="4" name="Category Name4"/>
        <myid id="5" name="Category Name5"/>
        <myid id="6" name="Category Name6"/>
        <myid id="7" name="Category Name7"/>
        <myid id="8" name="Category Name8"/>
        <myid id="9" name="Category Name9"/>
    </ids>
</mapids>');

- запрос

SELECT a.aId
      ,aXmlValues.* 
      ,(SELECT Xml2.value('(/mapids
                            /ids
                            /myid[@id=sql:column("aXmlValues.CategoryId")]
                            /@name)[1]','nvarchar(max)') 
        FROM @tblB b
        WHERE bID=200 /*however you find this...*/) AS CategoryName
FROM @tblA a
CROSS APPLY a.Xml1.nodes('/mainxml/category') aXml(c)
CROSS APPLY(SELECT aXml.c.value('@id','int') AS CategoryId
                  ,aXml.c.value('@ftype','int') AS CategoryType) aXmlValues;

Вкратце идея:

  • Мы используем APPLY ... .nodes(), чтобы получить категории таблицы «a» в отдельных строках (производный набор).
  • теперь мы можем снова используйте APPLY. Это уловка, позволяющая поместить значение XML в результирующий набор как обычный столбец .
  • Этот столбец можно поместить в XQuery против таблицы «b», используя sql:column() .
1 голос
/ 06 мая 2020

Я полагаю, вы, вероятно, захотите что-то вроде этого:

DECLARE @XML1 xml = '<mainxml>
     <category id="1" ftype="1"/>
     <category id="2" ftype="1"/>
     <category id="3" ftype="1"/>
</mainxml>';

DECLARE @XML2 xml = '<mapids>
    <ids>
        <myid id="1" name="Category Name1"/>
        <myid id="2" name="Category Name2"/>
        <myid id="3" name="Category Name3"/>
        <myid id="4" name="Category Name4"/>
        <myid id="5" name="Category Name5"/>
        <myid id="6" name="Category Name6"/>
        <myid id="7" name="Category Name7"/>
        <myid id="8" name="Category Name8"/>
        <myid id="9" name="Category Name9"/>
    </ids>
</mapids>';

SELECT X1.c.value('@id','int') AS id,
       X2.mi.value('@id','int') AS categoryid,  --Seem silly to have this value twice
       X2.mi.value('@name','varchar(30)') AS categoryname
FROM (VALUES(@XML1)) V1(X)
     CROSS APPLY (VALUES(@XML2)) V2(X)
     CROSS APPLY V1.X.nodes('/mainxml/category')X1(c)
     CROSS APPLY V2.X.nodes('/mapids/ids/myid')X2(mi)
WHERE X1.c.value('@id','int') = X2.mi.value('@id','int');
...