Разобрать SQL XML обратно в столбцы SQL - PullRequest
0 голосов
/ 09 марта 2012

Мой запрос возвращает все сделанные звонки.Мне нужно разделить возвращаемые значения 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 ]

1 голос
/ 09 марта 2012

Встроенный синтаксический анализатор XML позволяет вам превращать XML обратно в строки, а не в столбцы.Единственная возможная вещь, которую вы можете сделать, - это "отменить" агрегацию XML.Пожалуйста, ознакомьтесь с темой XML на SQL-сервере: 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 это создать сводную таблицу с произвольным числом столбцов (думал, что это было бы хорошо!)

0 голосов
/ 09 марта 2012

Вы используете XML для агрегирования данных по аккаунту. Я думаю, что вы вообще избегаете XML и используете конструкцию ROW_NUMBER () OVER (), чтобы получить последние 4 вызова в пределах диапазона дат для каждой учетной записи, а затем выполнить поворот с помощью оператора PIVOT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...