将SQL XML解析回SQL列

时间:2012-03-08 20:01:52

标签: sql sql-server sql-server-2008 tsql

我的查询返回所有拨打的电话。我需要将返回的XML值分成4列:

FirstCallDate,SecondCallDate,ThirdCallDate,LastCallDate。

当前查询:

SELECT AllCalls FROM
(
SELECT  
          (  SELECT startdate
            FROM mycalls i WITH (NOLOCK) WHERE i.phone = d.phone  FOR XML AUTO)
            AS AllCalls

  FROM [MYDB].[dbo].[Accounts] d WITH (NOLOCK)   
  WHERE SubmittedDate BETWEEN @MyStartDate AND @MyEndDate

) e

有时会返回:

  • NULL
  • i startdate =“2012-02-29T13:50:37”/>
  • i startdate =“2012-02-29T14:20:58”/> i startdate =“2012-02-29T14:21:13”/> (删除了开始括号)
  • 3 +日期
  • 4 +日期
  • 5 +日期

所以我的返回查询应该看起来像下面的sql,但每列只能保存1个日期。

    SELECT FirstCallDate, SecondCallDate, ThirdCallDate, LastCallDate
 FROM
    (
    SELECT  
              (  SELECT startdate
                FROM mycalls i WITH (NOLOCK) WHERE i.phone = d.phone  FOR XML AUTO)
                AS AllCalls

      FROM [MYDB].[dbo].[Accounts] d WITH (NOLOCK)   
      WHERE SubmittedDate BETWEEN @MyStartDate AND @MyEndDate

    ) e

关于如何将XML解析回SQL列的任何想法?

2 个答案:

答案 0 :(得分:1)

内置的XML解析器允许您将XML转换回行而不是列。您唯一可以做的就是基本上“撤消”XML聚合。请参阅SQL Server中的XML主题:http://msdn.microsoft.com/en-us/library/ms189887.aspx。这个子主题我在名称空间上用作参考:http://msdn.microsoft.com/en-us/library/ms177400.aspx

从那里你可以随意转动结果。我已经调整了您的查询:

WITH XMLNAMESPACES ('uri' as ns1)
SELECT phone, [1] AS FirstCall, [2] As SecondCall, [3] As ThirdCall, [4] As LastCall
FROM   (SELECT RN, phone, IndexRef
        FROM   (SELECT phone, CAST((SELECT StartDate as 'ns1:StartDate'
                      FROM   mycalls i WITH (NOLOCK) WHERE i.phone = d.phone FOR XML RAW('ns1:Prod'), ELEMENTS) AS XML) AS AllCalls
                FROM   [mydb].[dbo].[Accounts] d
                WHERE  phone in (31304,35549,39794,42711,51201,52529)) ns1
               CROSS APPLY (SELECT row_number() over (order by relop.value('.','DateTime')) RN, relop.value('.','DateTime') AS CallLog 
                              FROM ns1.AllCalls.nodes( N'//ns1:StartDate') AS ro(relop)) r) X
       PIVOT(MAX(CallLog) FOR RN IN ([1],[2],[3],[4])) P

显然,对于这个查询,XML在中间只是膨胀,可以跳过。(查询跟随)。但是,如果您从直接查询以外的某些源绑定到XML输出,则此方法很有用。

不使用XML,更容易。

SELECT P.phone, p.[1] AS FirstCallDate, p.[2] AS SecondCallDate, p.[3] AS ThirdCallDate, p.[4] AS LastCallDate
FROM   (SELECT ROW_NUMBER() OVER (PARTITION BY i.phone ORDER BY i.StartDate) i.phone, CallOrder, StartDate
        FROM   [mydb].[dbo].[Accounts] d
               JOIN mycalls i ON d.phone = i.phone
        WHERE  d.SubmittedDate BETWEEN @MyStartDate AND @MyEndDate) X
       PIVOT (MAX(StartDate) FOR CallOrder IN ([1], [2], [3], [4])) P

在SQL的上下文中你无法做的是创建一个具有任意数量列的数据透视图(认为肯定会很好!)

答案 1 :(得分:0)

您正在使用XML按帐户汇总数据。我想你完全避免使用XML并使用ROW_NUMBER()OVER()构造来获取每个帐户的日期范围内的最后4个调用,然后使用PIVOT运算符进行透视。