1

我已经阅读了很多关于该主题的帖子,但似乎并没有完全得到我想要的。

拥有四个表:ProductProduct_VersionProduct_Version_RuleRule并相应地创建记录集...

(注意自我继承InheritsFromID。启用所谓的Product Chain。理论上Product可以无限地继承自身,即制作一个永无止境的Product Chain,但是 IRL 一个Product继承链不再是三到五个 Product 遗产。)

SELECT
    Product.ProductID AS ID,
    Product.InheritsFromID,
    Product.Name AS ProductName,
    Product_Version.Name AS VersionName,
    -- Note, I have no real use for table *Product_Version_Rule*,
    -- I'm just join-using it below to get to *Rule*(Name).
    [Rule].Name AS RuleName,
    [Rule].Value AS RuleValue
FROM
(
    (
        Product 
        FULL OUTER JOIN Product_Version
            ON Product.ProductID = Product_Version.ProductID
    )
    FULL OUTER JOIN Product_Version_Rule
        ON Product_Version.ProductVersionID
            = Product_Version_Rule.ProductVersionID
)
LEFT JOIN [Rule]
    ON Product_Version_Rule.RuleID = [Rule].RuleID

... 导致...

row |  ID  InheritsFromID  ProductName     VersionName  RuleName  RuleValue |  note
----+-----------------------------------------------------------------------+------
 1  |  1   NULL            ProdTemplateA   (0)          a         5         |  *
 2  |  1   NULL            ProdTemplateA   (0)          b         15        |  *
 3  |  2   1               ProdComponentA  (0)          d         3         |  **
 4  |  2   1               ProdComponentA  (0)          c         11        |  **
 5  |  3   2               ProdEndA        (0)          s         1         |  ***
 6  |  3   2               ProdEndA        (1)          t         hello     |  ***
 7  |  4   NULL            ProdTemplateB   (0)          a         3         |  *
 8  |  5   4               ProdEndB        (1)          c         21        |  ***

* 一个“Start”-productcomponent,因为它不继承自父级。

** 一个“中间”产品组件,因为它既继承自父组件,又继承了子组件。

*** 一个“End”-productcomponent,因为没有人继承它。

但是,我希望它以分层方式呈现,最好是在 XML 中。但是用 just 完成查询FOR XML AUTO, ELEMENTS并不能解决问题,因为我想要一个嵌套的结果集,即:

<Product>
  <ID>1</ID>
  <InheritsFromID/>
  <ProductName>ProdTemplateA</ProductName>
  <Product_Version>
    <VersionName>(0)</VersionName>
    <Rule>
      <RuleName>a</RuleName>
      <RuleValue>5</RuleValue>
    </Rule>
    <Rule>
      <RuleName>b</RuleName>
      <RuleValue>15</RuleValue>
    </Rule>
  </Product_Version>
  <Product>
    <ID>2</ID>
    <InheritsFromID>1</InheritsFromID>
    <ProductName>ProdComponentA</ProductName>
    <Product_Version>
      <VersionName>(0)</VersionName>
      <Rule>
        <RuleName>d</RuleName>
        <RuleValue>3</RuleValue>
      </Rule>
      <Rule>
        <RuleName>c</RuleName>
        <RuleValue>13</RuleValue>
      </Rule>
    </Product_Version>
    <Product>
      <ID>3</ID>
      <InheritsFromID>2</InheritsFromID>
      <ProductName>ProdEndA</ProductName>
      <Product_Version>
        <VersionName>(0)</VersionName>
        <Rule>
          <RuleName>s</RuleName>
          <RuleValue>1</RuleValue>
        </Rule>
      </Product_Version>
      <Product_Version>
        <VersionName>(1)</VersionName>
        <Rule>
          <RuleName>t</RuleName>
          <RuleValue>hello</RuleValue>
        </Rule>
      </Product_Version>
    </Product>
  </Product>
</Product>
<Product>
  <ID>4</ID>
  <InheritsFromID/>
  <ProductName>ProdTemplateB</ProductName>
  <Product_Version>
    <VersionName>(0)</VersionName>
    <Rule>
      <RuleName>a</RuleName>
      <RuleValue>3</RuleValue>
    </Rule>
  </Product_Version>
  <Product>
    <ID>5</ID>
    <InheritsFromID>4</InheritsFromID>
    <ProductName>ProdEndB</ProductName>
    <Product_Version>
      <VersionName>(1)</VersionName>
      <Rule>
        <RuleName>c</RuleName>
        <RuleValue>21</RuleValue>
      </Rule>
    </Product_Version>
  </Product>
</Product>

关于如何实现上述结构的任何想法?

我正在考虑 CTE,但我无法真正理解它。

4

1 回答 1

0

假设架构:

DROP TABLE Product
DROP TABLE Product_Version
DROP TABLE Product_Version_Rule
DROP TABLE [Rule] 

CREATE TABLE Product (ProductID INT, InheritsFromID INT, Name VARCHAR(100))
CREATE TABLE Product_Version
    (ProductVersionID INT, ProductID INT, Name VARCHAR(100))
CREATE TABLE Product_Version_Rule (ProductVersionID INT, RuleID INT)
CREATE TABLE [Rule] (RuleId INT, Name VARCHAR(100), Value VARCHAR(100))

样本数据:

INSERT Product VALUES
    (1, NULL, 'ProdTemplateA'),
    (2, 1, 'ProdComponentA'),
    (3, 2, 'ProdEndA'),
    (4, NULL, 'ProdTemplateB'),
    (5, 4, 'ProdEndB')

INSERT Product_Version VALUES
    (1, 1, '(0)'),
    (2, 2, '(0)'),
    (3, 3, '(0)'),
    (4, 3, '(1)'),
    (5, 4, '(0)'),
    (6, 5, '(1)')


INSERT [Rule] VALUES
    (1, 'a', '5'),
    (2, 'b', '15'),
    (3, 'd', '3'),
    (4, 'c', '11'),
    (5, 's', '1'),
    (6, 't', 'hello'),
    (7, 'a', '3'),
    (8, 'c', '21')


INSERT Product_Version_Rule VALUES
    (1, 1),
    (1, 2),
    (2, 3),
    (2, 4),
    (3, 5),
    (4, 6),
    (5, 7),
    (6, 8)

递归用户定义函数:

CREATE FUNCTION dbo.ProductXML(@ParentProductID INT)
RETURNS XML
AS
BEGIN
    RETURN (
        SELECT
            ProductID AS ID,
            (
                SELECT Product.InheritsFromID
                FOR XML PATH ('InheritsFromID'), TYPE
            ),
            Name AS [ProductName],
            (
                SELECT
                    Product_Version.Name AS [VersionName],
                    (
                        SELECT
                            [Rule].Name AS [RuleName],
                            [Rule].Value AS [RuleValue]
                        FROM Product_Version_Rule
                        LEFT JOIN [Rule]
                            ON Product_Version_Rule.RuleID = [Rule].RuleID
                        WHERE Product_Version.ProductVersionID
                            = Product_Version_Rule.ProductVersionID
                        FOR XML PATH ('Rule'), TYPE
                    )
                FROM Product_Version
                WHERE Product.ProductID = Product_Version.ProductID
                FOR XML PATH (''), ROOT ('Product_Version'), TYPE
            ),
            (
                SELECT dbo.ProductXML(ProductID)
            )
        FROM Product
        WHERE InheritsFromID = @ParentProductID
        OR (InheritsFromID IS NULL AND @ParentProductID IS NULL)
        FOR XML PATH ('Product'), TYPE
    )
END

用法:

SELECT dbo.ProductXML(NULL)

输出:

<Product>
  <ID>1</ID>
  <InheritsFromID />
  <ProductName>ProdTemplateA</ProductName>
  <Product_Version>
    <VersionName>(0)</VersionName>
    <Rule>
      <RuleName>a</RuleName>
      <RuleValue>5</RuleValue>
    </Rule>
    <Rule>
      <RuleName>b</RuleName>
      <RuleValue>15</RuleValue>
    </Rule>
  </Product_Version>
  <Product>
    <ID>2</ID>
    <InheritsFromID>
      <InheritsFromID>1</InheritsFromID>
    </InheritsFromID>
    <ProductName>ProdComponentA</ProductName>
    <Product_Version>
      <VersionName>(0)</VersionName>
      <Rule>
        <RuleName>d</RuleName>
        <RuleValue>3</RuleValue>
      </Rule>
      <Rule>
        <RuleName>c</RuleName>
        <RuleValue>11</RuleValue>
      </Rule>
    </Product_Version>
    <Product>
      <ID>3</ID>
      <InheritsFromID>
        <InheritsFromID>2</InheritsFromID>
      </InheritsFromID>
      <ProductName>ProdEndA</ProductName>
      <Product_Version>
        <VersionName>(0)</VersionName>
        <Rule>
          <RuleName>s</RuleName>
          <RuleValue>1</RuleValue>
        </Rule>
        <VersionName>(1)</VersionName>
        <Rule>
          <RuleName>t</RuleName>
          <RuleValue>hello</RuleValue>
        </Rule>
      </Product_Version>
    </Product>
  </Product>
</Product>
<Product>
  <ID>4</ID>
  <InheritsFromID />
  <ProductName>ProdTemplateB</ProductName>
  <Product_Version>
    <VersionName>(0)</VersionName>
    <Rule>
      <RuleName>a</RuleName>
      <RuleValue>3</RuleValue>
    </Rule>
  </Product_Version>
  <Product>
    <ID>5</ID>
    <InheritsFromID>
      <InheritsFromID>4</InheritsFromID>
    </InheritsFromID>
    <ProductName>ProdEndB</ProductName>
    <Product_Version>
      <VersionName>(1)</VersionName>
      <Rule>
        <RuleName>c</RuleName>
        <RuleValue>21</RuleValue>
      </Rule>
    </Product_Version>
  </Product>
</Product>
于 2014-07-07T21:15:12.870 回答