【问题标题】:Having Trouble with FOR XML Path - No ConcatenatingFOR XML 路径有问题 - 没有连接
【发布时间】:2019-01-16 19:13:53
【问题描述】:

我有一种情况,订单可以包含多个许可证购买 - 如果订单确实包含多个许可证,我想在单个单元格中显示许可证说明,值以逗号分隔。如果我们使用的是 SQL 2017,我可以使用 STRING_AGG,但我们使用的是 SQL 2016,所以我正在尝试久经考验的真正 STUFF / FOR XML Path 方法。

从下面的屏幕截图中,客户 4341073 在订单 ID 18519173 上购买了两次许可证:

当我将 STUFF / FOR XML 路径添加到 T-SQL 时,我无法实现在同一记录中显示许可证描述的预期结果 - 每个许可证仍然有它自己的行。

SELECT   x.CustomerID ,
         x.ATOLicenseTypeID ,
         x.ATOLicense ,
         x.AuthorizationBeginDate ,
         x.AuthorizationEndDate ,
         x.OrderID ,
         x.OrderDate ,
         STUFF ( (
                 SELECT ',' + lt.description
                 FROM   dbo.LicenseTypes AS lt
                 --INNER JOIN #XMLPATH ON lt.id = x.OrderLicenseTypeID
                 WHERE  lt.id = x.OrderLicenseTypeID
                 --GROUP BY ',' + lt.description
                 FOR XML PATH ( '' )
             ) , 1 , 1 , '' ) AS Licenses
FROM     #XMLPATH AS x
--GROUP BY x.CustomerID ,
--         x.ATOLicenseTypeID ,
--         x.ATOLicense ,
--         x.AuthorizationBeginDate ,
--         x.AuthorizationEndDate ,
--         x.OrderID ,
--         x.OrderDate ,
--         x.OrderLicenseTypeID;

我尝试了不同的方法将子查询加入到外部查询中,并添加和删除了 GROUP BY 以达到预期的结果,但对我来说没有任何效果。

关于我在哪里执行此查询有什么建议吗?

样本数据集:

DROP TABLE IF EXISTS #XMLPATH;

CREATE TABLE #XMLPATH
    (
        CustomerID INT ,
        ATOLicenseTypeID INT ,
        ATOLicense VARCHAR (500) ,
        AuthorizationBeginDate DATE ,
        AuthorizationEndDate DATE ,
        OrderID INT ,
        OrderDate DATETIME ,
        OrderLicenseTypeID INT
    );
INSERT INTO #XMLPATH
VALUES ( 4341073, 52, 'Temporary Resident Fishing', N'2019-01-07T00:00:00', N'2019-01-07T00:00:00', 18519136, N'2019-01-07T12:01:55.317', 2141 ) ,
       ( 4341073, 52, 'Temporary Resident Fishing', N'2019-01-07T00:00:00', N'2019-01-07T00:00:00', 18519173, N'2019-01-07T12:34:13.107', 204 ) ,
       ( 4341073, 52, 'Temporary Resident Fishing', N'2019-01-07T00:00:00', N'2019-01-07T00:00:00', 18519173, N'2019-01-07T12:34:13.107', 2141 );

SELECT * FROM #XMLPATH;

SELECT   x.CustomerID ,
         x.ATOLicenseTypeID ,
         x.ATOLicense ,
         x.AuthorizationBeginDate ,
         x.AuthorizationEndDate ,
         x.OrderID ,
         x.OrderDate ,
         STUFF ( (
                 SELECT ',' + lt.description
                 FROM   dbo.LicenseTypes AS lt
                 --INNER JOIN #XMLPATH ON lt.id = x.OrderLicenseTypeID
                 WHERE  lt.id = x.OrderLicenseTypeID
                 --GROUP BY ',' + lt.description
                 FOR XML PATH ( '' )
             ) , 1 , 1 , '' ) AS Licenses
FROM     #XMLPATH AS x
GROUP BY x.CustomerID ,
         x.ATOLicenseTypeID ,
         x.ATOLicense ,
         x.AuthorizationBeginDate ,
         x.AuthorizationEndDate ,
         x.OrderID ,
         x.OrderDate ,
         x.OrderLicenseTypeID;

【问题讨论】:

    标签: sql xml sql-server-2016


    【解决方案1】:

    为了将一个OrderID 的所有行作为一个结果行,您不能在GROUP BY 中包含分隔信息(OrderLicenseTypeID)。但是您遇到了遇到的问题:您不能在 FOR XML 构造中使用此 ID。

    诀窍是(如您的评论外试验所示),将源表添加到子选择中,并在其中使用分组列进行过滤。但是您必须使用不同的别名来将它们作为两个不同的集合来处理。试试这个:

    (我不得不再添加一个临时表来测试这个......)

    SELECT   x.CustomerID ,
             x.ATOLicenseTypeID ,
             x.ATOLicense ,
             x.AuthorizationBeginDate ,
             x.AuthorizationEndDate ,
             x.OrderID ,
             x.OrderDate ,
             STUFF ( (
                     SELECT ',' + lt.description
                     FROM   #XMLPATH x2 
                     INNER JOIN #LicenseTypes AS lt ON lt.id=x2.OrderLicenseTypeID
                     WHERE  x2.OrderID = x.OrderID --you might need to add more columns here....
                     --in most cases we want to add an ORDER BY
                     FOR XML PATH ( '' )
                 ) , 1 , 1 , '' ) AS Licenses
    FROM     #XMLPATH AS x
    GROUP BY x.CustomerID ,
             x.ATOLicenseTypeID ,
             x.ATOLicense ,
             x.AuthorizationBeginDate ,
             x.AuthorizationEndDate ,
             x.OrderID ,
             x.OrderDate;
    

    顺便说一句:从 v2017 开始有 STRING_AGG(),这让这变得更容易...

    【讨论】:

    • 谢谢!等我回去工作,我会检查一下。
    • 稍作修改即可工作。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 2012-12-14
    • 2023-03-07
    • 1970-01-01
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多