从SQL Server表生成动态多级XML文件

时间:2016-06-12 11:23:55

标签: sql-server xml merge

我有一个包含5个表的数据库。连接3个表。

我创建了一个表,其中所有数据都已合并。此表有一个GroupLevel列,其中包含level nr。每个级别保持随后的较低级别,例如第1组持有第2组。

我的第一张表包含产品:

 ProductID  ProductLanguageID   ProductDefaultShopID  ProductNumber ProductName ProductPrice
    100101@@SHOP1   LANG2           SHOP1                 100101            AAA         159,61
    100102@@SHOP1   LANG2           SHOP1                 100102            BBB         159,61
    100105@@SHOP1   LANG2           SHOP1                 100105            CCC         159,61

第二个有小组:

GroupID         GroupLanguageID      GroupName  GroupNumber
1@@SHOP1    LANG2                ABC        1
1.01@@SHOP1 LANG2                BCD    1.01
1.02@@SHOP1 LANG2                CDE    1.02
1.03@@SHOP1 LANG2                DEF    1.03

第三语言

LanguageID  LanguageCode2   LanguageName    LanguageNativeName
LANG1           En          English         English
LANG2           De          German          Deutsch

我还有2个表与另一个表没有任何连接:

集团关系表

GroupRelationsGroupID   GroupRelationsParentID
1.01@@SHOP1         1@@SHOP1
1.02@@SHOP1         1@@SHOP1
1.02@@SHOP1         1@@SHOP1

集团产品关系表

GroupProductRelationGroupID GroupProductRelationProductID
1.01@@SHOP1                 576134@@SHOP1
1.01@@SHOP1                 327112@@SHOP1
1.01@@SHOP1                 457168@@SHOP1
1.01@@SHOP1                 457220@@SHOP1
1.03@@SHOP1                 457221@@SHOP1
1.03@@SHOP1                 163704@@SHOP1
1.03@@SHOP1                 163705@@SHOP1
1.03@@SHOP1                 163706@@SHOP1

我创建了一个表,其中所有数据都已合并。此表有一个GroupLevel列,它包含一个级别nr。每个级别保持随后的较低级别,例如第1组持有第2组,如下表所示

GroupLevel  GroupID GroupLanguageID GroupName  GroupNumber  ParentGroupID  GroupProductRelationGroupID GroupProductRelationProductID  ProductID ProductLanguageID  ProductNumber  ProductName   ProductPrice
1       1@@SHOP1    LANG2           ABC    1            NULL           NULL                    NULL                           NULL          NULL               NULL           NULL          NULL
2       1.01@@SHOP1 LANG2           BCD    1.01         1@@SHOP1       1.01@@SHOP1             457163@@SHOP1              457163@@SHOP1 LANG2              457163     ProductName   299,81
2       1.01@@SHOP1 LANG2           BCD    1.01         1@@SHOP1       1.01@@SHOP1             457162@@SHOP1              457162@@SHOP1 LANG2              457162     ProductName   163,14
2       1.03@@SHOP1 LANG2           DEF    1.03         1@@SHOP1       1.03@@SHOP1             159151@@SHOP1              159151@@SHOP1 LANG2              159151     ProductName   10
2       1.03@@SHOP1 LANG2           DEF    1.03         1@@SHOP1       1.03@@SHOP1             159150@@SHOP1              159150@@SHOP1 LANG2              159150     ProductName   10
2       1.03@@SHOP1 LANG2           DEF    1.02         1@@SHOP1       1.03@@SHOP1             159122@@SHOP1              159122@@SHOP1 LANG2              159122     ProductName   309,35
3       1.13@@SHOP1 LANG2           GGG    1.13         1.03@@SHOP1    1.13@@SHOP1             3459652@@SHOP1             3459652@@SHOP1LANG2              3459652    ProductName   309,35  
4       1.14@@SHOP1 LANG2           BBB    1.14         1.13@@SHOP1    1.13@@SHOP1             564326@@SHOP1              564326@@SHOP1 LANG2              564326     ProductName   309,35                          

我的问题是如何创建一个最多3个级别的动态XML文件,其中第三个级别之后的所有项目都合并到(包括在)第3级别。我还需要这些级别中的每个项目(合并到第三个级别)都有一个属性,表示/显示它们最初属于哪个级别。因此,例如,如果我有5个级别,4级和5级合并到级别3,则级别4中的所有项目都应该有一个标记“先前在4级”和5级“之前在5级”。无论有多少级别,这都应该有效。

我创建了代码,但它根本不能正常工作

SELECT lvl1.GroupName AS groupName, lvl1.GroupNumber
      ,(
            SELECT prod1.ProductName AS itemName
            ,prod1.ProductNumber AS itemNumber,
            prod1.ProductPrice AS itemPrice,
            prod1.GroupID,
            prod1.GroupName                      
            FROM #tmpFullResult AS prod1
            WHERE prod1.GroupLevel=1 
            AND prod1.GroupID=lvl1.GroupID             
            FOR XML PATH('product'),ROOT('products'),TYPE
                )
                ,(  

        SELECT  lvl2.GroupName AS groupName, lvl2.GroupNumber
           ,(

    SELECT  prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber
           ,prod.ProductPrice AS itemPrice
    FROM #tmpFullResult AS prod
    WHERE prod.ProductID IS NOT NULL 
        AND prod.GroupLevel=2
        AND prod.ProductID=lvl2.ProductID
        AND prod.GroupID=lvl2.GroupID
        FOR XML PATH('product'),ROOT('products'),TYPE
         )                      
        FROM #tmpFullResult AS lvl2
        WHERE lvl2.GroupLevel=2 
        AND lvl2.ParentGroupID=lvl1.GroupID
        group by lvl2.GroupName , lvl2.GroupNumber,lvl2.GroupID, lvl2.ProductID
       FOR XML PATH('productGroup2'),TYPE
       )         
FROM #tmpFullResult AS lvl1
WHERE lvl1.ParentGroupID IS NULL
group by lvl1.GroupName , lvl1.GroupNumber,lvl1.GroupID, lvl1.ProductID
FOR XML PATH('productgroup1'),ROOT('root')

GO

我需要做的一个例子:

select '<?xml version="1.0" encoding="ISO-8859-1" ?>' +
(

SELECT lvl1.GroupName AS groupName
      ,(
                SELECT prod1.ProductName, prod1.ProductNumber AS itemNumber
                ,prod1.ProductPrice AS itemPrice
                FROM tmpFullResultInDesign AS prod1
                WHERE prod1.ProductID IS NOT NULL 
                AND prod1.GroupLevel=1
                AND prod1.ProductID=lvl1.ProductID
                AND prod1.GroupID=lvl1.GroupID


                FOR XML PATH('productLevel_1'),ROOT('products'),TYPE
                )
                ,(  
SELECT  lvl2.GroupName AS 'GroupName'
                ,(
                SELECT prod2.ProductName  AS ProductName ,prod2.ProductNumber AS itemNumber
                ,prod2.ProductPrice AS itemPrice, prod2.GroupID
                FROM tmpFullResultInDesign AS prod2
                WHERE prod2.ProductID IS NOT NULL 
                AND prod2.GroupLevel=2
                AND prod2.ProductID=lvl2.ProductID
                AND prod2.GroupID=lvl2.GroupID
                order by groupName
                FOR XML PATH('productLevel_2'),ROOT('products'),TYPE  
                )
                ,(
SELECT lvl3.GroupName AS groupName
                ,(
                SELECT prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber
                ,prod.ProductPrice AS itemPrice    
                FROM tmpFullResultInDesign AS prod
                WHERE prod.ProductID IS NOT NULL 
                AND prod.GroupLevel=3
                AND prod.ProductID= lvl3.ProductID
                AND prod.GroupID=lvl3.GroupID
                FOR XML PATH('productLevel_3'),ROOT('products'),TYPE
                )               
                ,(

                SELECT  prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber
                ,prod.ProductPrice AS itemPrice
                FROM tmpFullResultInDesign AS prod
                WHERE prod.ProductID IS NOT NULL 
                AND prod.GroupLevel=3
                FOR XML PATH('productLevel_previously_level_4'),ROOT('products'),TYPE  
                )

,(

                SELECT  prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber
                ,prod.ProductPrice AS itemPrice
                FROM tmpFullResultInDesign AS prod
                WHERE prod.ProductID IS NOT NULL 
                AND prod.GroupLevel=5
                FOR XML PATH('productLevel_previously_level_5'),ROOT('products'),TYPE  
                )

FROM tmpFullResultInDesign AS lvl3
WHERE lvl3.GroupLevel=3 
AND lvl3.ParentGroupID=lvl2.GroupID
FOR XML PATH('productGroup3'),TYPE, ELEMENTS
                )    
FROM tmpFullResultInDesign AS lvl2
WHERE lvl2.GroupLevel=2 
AND lvl2.ParentGroupID=lvl1.GroupID
order by lvl2.GroupName
FOR XML PATH('productGroup2'),TYPE, ELEMENTS 
                )      
FROM tmpFullResultInDesign AS lvl1
WHERE lvl1.ParentGroupID IS NULL
order by GroupNumber
FOR XML PATH('productGroup1'),ROOT('root')
)

XML输出就像这个例子:

<?xml version="1.0" encoding="UTF-8"?>
<root>
       <productGroup1>
              <groupName>Kosmetik</groupName>
              <productGroup2>
                     <GroupName>Face</GroupName>
                     <products>
                            <productLevel_2 id="Product1">
                                   <ProductName>AAAAA!</ProductName>
                                   <itemNumber>457162</itemNumber>
                                   <itemPrice>1.02</itemPrice>
                                   <GroupID>1.01@@SHOP1</GroupID>
                               </productLevel_2>
                            <productLevel_2 id="Product2">
                                   <ProductName>BBBBB!</ProductName>
                                   <itemNumber>43434234</itemNumber>
                                   <itemPrice>134.3434</itemPrice>
                                   <GroupID>1.01@@SHOP1</GroupID>
                               </productLevel_2>
                        </products>
                     <productGroup3>
                            <groupName>FFFFFFF</groupName>
                            <products>
                                   <productLevel_3 id="Product1">
                                          <itemNumber>123@1</itemNumber>
                                          <itemPrice>1.230000000000000e+002</itemPrice>
                                      </productLevel_3>
                               </products>
                            <products>
                                   <productLevel_previously_level_4 id="Product1">
                                          <itemNumber>23234545</itemNumber>
                                          <itemPrice>34.676</itemPrice>
                                      </productLevel_previously_level_4>
                                   <productLevel_previously_level_4 id="Product2">
                                          <itemNumber>23234545</itemNumber>
                                          <itemPrice>34.676</itemPrice>
                                      </productLevel_previously_level_4>
                               </products>
                        </productGroup3>
                 </productGroup2>
          </productGroup1>
   </root>

问题解释: 我需要使用n级(即级别n + 1应该达到级别n)。我试着再次解释...... 我有几个级别的产品:

level 1 + products 
level 2 + products 
level 3 + products ... 
level n + products. 

我的想法是,如果我选择1级,所有级别大于1的产品(即2,3,4 ... n)都会聚合到1级:

<productGroup1 GroupID="10@@SHOP1">
       <GroupName>AAA</GroupName>
       <GroupLevel>1</GroupLevel>
       <products>
              <product>
                     <ProductName>CCC</ProductName>
                 </product>
          </products>
       <products>
              <product>
                     <ProductName>Mem</ProductName>
                 </product>
          </products>
   </productGroup1>

如果我选择级别2,级别1是完整的,并且级别大于2(即3,4 ... n)的所有产品都会聚合到级别2。 所有级别都是如此(没有限制)。

我可以将CTE放入存储过程吗?

1 个答案:

答案 0 :(得分:1)

我已经采用了“我需要做的一个例子”并用这个替换了4级和5级查询:

-- Levels 3+
SELECT prod.ProductName  AS '@id', prod.GroupLevel AS '@PreviousGroupLevel', prod.ProductNumber AS itemNumber,
    prod.ProductPrice AS itemPrice
FROM #tmpFullResult AS prod
WHERE prod.ProductID IS NOT NULL 
    AND prod.GroupLevel>= 3
--FOR XML PATH('productLevel_previously_level_4'),ROOT('products'),TYPE
FOR XML PATH('productLevel_HigherLevels'),ROOT('products'),TYPE

在上面,请注意,我正在使用属性“@PreviousGroupLevel”,并且XML PATH已更改为“productLevel_HigherLevels”。
整体查询如下(它需要#tmpFullResult表):

SELECT lvl1.GroupName AS groupName,
    (
        SELECT prod1.ProductName, prod1.ProductNumber AS itemNumber
            ,prod1.ProductPrice AS itemPrice
        FROM #tmpFullResult AS prod1
        WHERE prod1.ProductID IS NOT NULL 
            AND prod1.GroupLevel = 1
            AND prod1.ProductID = lvl1.ProductID
            AND prod1.GroupID = lvl1.GroupID
        FOR XML PATH('productLevel_1'),ROOT('products'),TYPE
    ),
    (  
        SELECT  lvl2.GroupName AS 'GroupName',
            (
                SELECT prod2.ProductName  AS ProductName ,prod2.ProductNumber AS itemNumber,
                    prod2.ProductPrice AS itemPrice, prod2.GroupID
                FROM #tmpFullResult AS prod2
                WHERE prod2.ProductID IS NOT NULL 
                    AND prod2.GroupLevel=2
                    AND prod2.ProductID=lvl2.ProductID
                    AND prod2.GroupID=lvl2.GroupID
                ORDER BY groupName
                FOR XML PATH('productLevel_2'),ROOT('products'),TYPE  
            ),
            (
                SELECT lvl3.GroupName AS groupName
                    ,(
                        SELECT prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber,
                            prod.ProductPrice AS itemPrice    
                        FROM #tmpFullResult AS prod
                        WHERE prod.ProductID IS NOT NULL 
                            AND prod.GroupLevel = 3
                            AND prod.ProductID = lvl3.ProductID
                            AND prod.GroupID = lvl3.GroupID
                        FOR XML PATH('productLevel_3'),ROOT('products'),TYPE
                    )               
                    ,(
                        -- Levels 3+
                        SELECT prod.ProductName  AS '@id', prod.GroupLevel AS '@PreviousGroupLevel', prod.ProductNumber AS itemNumber,
                            prod.ProductPrice AS itemPrice
                        FROM #tmpFullResult AS prod
                        WHERE prod.ProductID IS NOT NULL 
                            AND prod.GroupLevel>= 3
                        --FOR XML PATH('productLevel_previously_level_4'),ROOT('products'),TYPE
                        FOR XML PATH('productLevel_HigherLevels'),ROOT('products'),TYPE  
                    )/*,
                    (
                        SELECT  prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber,
                            prod.ProductPrice AS itemPrice
                        FROM #tmpFullResult AS prod
                        WHERE prod.ProductID IS NOT NULL 
                            AND prod.GroupLevel=5
                        FOR XML PATH('productLevel_previously_level_5'),ROOT('products'),TYPE  
                    )*/
                FROM #tmpFullResult AS lvl3
                WHERE lvl3.GroupLevel=3 
                AND lvl3.ParentGroupID=lvl2.GroupID
                FOR XML PATH('productGroup3'),TYPE, ELEMENTS
            )    
        FROM #tmpFullResult AS lvl2
        WHERE lvl2.GroupLevel=2 
        AND lvl2.ParentGroupID=lvl1.GroupID
        order by lvl2.GroupName
        FOR XML PATH('productGroup2'),TYPE, ELEMENTS 
    )      
FROM #tmpFullResult AS lvl1
WHERE lvl1.ParentGroupID IS NULL
order by GroupNumber
FOR XML PATH('productGroup1'),ROOT('root')

我希望这是你一直在寻找的。

<强>更新 样本数据:

CREATE TABLE #tmpFullResult( GroupLevel INT, GroupID VARCHAR( 20 ) NULL,
    GroupLanguageID VARCHAR( 20 ) NULL, GroupName VARCHAR( 20 ) NULL,
    GroupNumber DECIMAL( 10, 3 ) NULL, ParentGroupID VARCHAR( 20 ) NULL,
    GroupProductRelationGroupID VARCHAR( 20 ) NULL,
    GroupProductRelationProductID VARCHAR( 20 ) NULL,
    ProductID VARCHAR( 20 ) NULL, ProductLanguageID VARCHAR( 10 ) NULL,
    ProductNumber INT NULL, ProductName VARCHAR( 20 ) NULL, ProductPrice DECIMAL( 20, 4 ) NULL )

INSERT INTO #tmpFullResult
VALUES
( 1, '1@@SHOP1',    'LANG2', 'ABC',    1,  NULL,           NULL,         NULL,            NULL,            NULL,   NULL,        NULL,          NULL ),
( 2, '1.01@@SHOP1', 'LANG2', 'BCD', 1.01, '1@@SHOP1',    '1.01@@SHOP1', '457163@@SHOP1', '457163@@SHOP1', 'LANG2', 457163,     'ProductName', 299.81 ),
( 2, '1.01@@SHOP1', 'LANG2', 'BCD', 1.01, '1@@SHOP1',    '1.01@@SHOP1', '457162@@SHOP1', '457162@@SHOP1', 'LANG2', 457162,     'ProductName', 163.14 ),
( 2, '1.03@@SHOP1', 'LANG2', 'DEF', 1.03, '1@@SHOP1',    '1.03@@SHOP1', '159151@@SHOP1', '159151@@SHOP1', 'LANG2', 159151,     'ProductName', 10 ),
( 2, '1.03@@SHOP1', 'LANG2', 'DEF', 1.03, '1@@SHOP1',    '1.03@@SHOP1', '159150@@SHOP1', '159150@@SHOP1', 'LANG2', 159150,     'ProductName', 10 ),
( 2, '1.03@@SHOP1', 'LANG2', 'DEF', 1.02, '1@@SHOP1',    '1.03@@SHOP1', '159122@@SHOP1', '159122@@SHOP1', 'LANG2', 159122,     'ProductName', 309.35 ),
( 3, '1.13@@SHOP1', 'LANG2', 'GGG', 1.13, '1.03@@SHOP1', '1.03@@SHOP1', '3459652@@SHOP1','3459652@@SHOP1','LANG2', 3459652,    'ProductName', 309.35 ), 
( 4, '1.14@@SHOP1', 'LANG2', 'BBB', 1.14, '1.13@@SHOP1', '1.13@@SHOP1', '564326@@SHOP1', '564326@@SHOP1', 'LANG2', 564326,     'ProductName', 309.35 ),
( 5, '1.15@@SHOP1', 'LANG2', 'BBB', 1.14, '1.14@@SHOP1', '1.13@@SHOP1', '564326@@SHOP1', '564326@@SHOP1', 'LANG2', 564326,     'ProductName', 309.35 ),
( 3, '1.23@@SHOP1', 'LANG2', 'GGG', 1.13, '1.01@@SHOP1', '1.03@@SHOP1', '3459652@@SHOP1','3459652@@SHOP1','LANG2', 3459652,    'ProductName', 309.35 ), 
( 4, '1.24@@SHOP1', 'LANG2', 'BBB', 1.14, '1.23@@SHOP1', '1.13@@SHOP1', '564326@@SHOP1', '564326@@SHOP1', 'LANG2', 564326,     'ProductName', 309.35 ),
( 5, '1.25@@SHOP1', 'LANG2', 'BBB', 1.14, '1.24@@SHOP1', '1.13@@SHOP1', '564326@@SHOP1', '564326@@SHOP1', 'LANG2', 564326,     'ProductName', 309.35 )

下面的查询类似于上面的查询,除了我添加了一个CTE来计算所有更高级别组的GroupLevel 3 parentID:

;WITH productLevel_HigherLevels( GroupLevel, GroupID, GroupLanguageID, GroupName, GroupNumber, ParentGroupID,
        GroupProductRelationGroupID, GroupProductRelationProductID, ProductID, ProductLanguageID,
        ProductNumber, ProductName, ProductPrice )
AS  
-- Define the CTE query.  
(  
    SELECT GroupLevel, GroupID, GroupLanguageID, GroupName, GroupNumber, ParentGroupID,
        GroupProductRelationGroupID, GroupProductRelationProductID, ProductID, ProductLanguageID,
        ProductNumber, ProductName, ProductPrice
    FROM #tmpFullResult
    WHERE GroupLevel = 4 AND ProductID IS NOT NULL 
    UNION ALL
    SELECT HigherLevel.GroupLevel, HigherLevel.GroupID, HigherLevel.GroupLanguageID, HigherLevel.GroupName, HigherLevel.GroupNumber, LowerLevel.ParentGroupID,
        HigherLevel.GroupProductRelationGroupID, HigherLevel.GroupProductRelationProductID, HigherLevel.ProductID, HigherLevel.ProductLanguageID,
        HigherLevel.ProductNumber, HigherLevel.ProductName, HigherLevel.ProductPrice
    FROM productLevel_HigherLevels AS LowerLevel
        INNER JOIN #tmpFullResult AS HigherLevel
                ON HigherLevel.ProductID IS NOT NULL 
                    AND LowerLevel.GroupLevel + 1 = HigherLevel.GroupLevel
                    AND HigherLevel.ParentGroupID = LowerLevel.GroupID
)
SELECT lvl1.GroupName AS groupName,
    (
        SELECT prod1.ProductName, prod1.ProductNumber AS itemNumber
            ,prod1.ProductPrice AS itemPrice
        FROM #tmpFullResult AS prod1
        WHERE prod1.ProductID IS NOT NULL 
            AND prod1.GroupLevel = 1
            AND prod1.ProductID = lvl1.ProductID
            AND prod1.GroupID = lvl1.GroupID
        FOR XML PATH('productLevel_1'),ROOT('products'),TYPE
    ),
    (  
        SELECT  lvl2.GroupName AS 'GroupName',
            (
                SELECT prod2.ProductName  AS ProductName ,prod2.ProductNumber AS itemNumber,
                    prod2.ProductPrice AS itemPrice, prod2.GroupID
                FROM #tmpFullResult AS prod2
                WHERE prod2.ProductID IS NOT NULL 
                    AND prod2.GroupLevel=2
                    AND prod2.ProductID=lvl2.ProductID
                    AND prod2.GroupID=lvl2.GroupID
                ORDER BY groupName
                FOR XML PATH('productLevel_2'),ROOT('products'),TYPE  
            ),
            (
                SELECT lvl3.GroupName AS groupName
                    ,(
                        SELECT prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber,
                            prod.ProductPrice AS itemPrice    
                        FROM #tmpFullResult AS prod
                        WHERE prod.ProductID IS NOT NULL 
                            AND prod.GroupLevel = 3
                            AND prod.ProductID = lvl3.ProductID
                            AND prod.GroupID = lvl3.GroupID

                        FOR XML PATH('productLevel_3'),ROOT('products'),TYPE
                    )               
                    ,(
                        SELECT prod.ProductName  AS '@id', prod.GroupLevel AS '@PreviousGroupLevel', prod.ProductNumber AS itemNumber,
                            prod.ProductPrice AS itemPrice
                        FROM productLevel_HigherLevels AS prod
                        WHERE prod.ParentGroupID = lvl3.GroupID
                        --FOR XML PATH('productLevel_previously_level_4'),ROOT('products'),TYPE
                        FOR XML PATH('productLevel_HigherLevels'),ROOT('products'),TYPE  
                    )/*,
                    (
                        SELECT  prod.ProductName  AS '@id' ,prod.ProductNumber AS itemNumber,
                            prod.ProductPrice AS itemPrice
                        FROM #tmpFullResult AS prod
                        WHERE prod.ProductID IS NOT NULL 
                            AND prod.GroupLevel=5
                        FOR XML PATH('productLevel_previously_level_5'),ROOT('products'),TYPE  
                    )*/
                FROM #tmpFullResult AS lvl3
                WHERE lvl3.GroupLevel=3 
                AND lvl3.ParentGroupID=lvl2.GroupID
                FOR XML PATH('productGroup3'),TYPE, ELEMENTS
            )    
        FROM #tmpFullResult AS lvl2
        WHERE lvl2.GroupLevel=2 
        AND lvl2.ParentGroupID=lvl1.GroupID
        order by lvl2.GroupName
        FOR XML PATH('productGroup2'),TYPE, ELEMENTS 
    )      
FROM #tmpFullResult AS lvl1
WHERE lvl1.ParentGroupID IS NULL
order by GroupNumber
FOR XML PATH('productGroup1'),ROOT('root')