Mostrando las entradas con la etiqueta ROWS TO COLUMNS. Mostrar todas las entradas
Mostrando las entradas con la etiqueta ROWS TO COLUMNS. Mostrar todas las entradas

jueves, 1 de octubre de 2015

XML A TABLA


XML to TABLE




A continuación te mostraré como leer una cadena XMLdesde SQL Server para convertirlo en un formato tipo tabla.
Iniciamos con un XML sencillo:


<cliente>
       <id>57</id>
       <id>58</id>
       <id>59</id>

</cliente>

Para leer el xml que muestro en la parte superior se hace lo siguiente:

SELECT 
         t.c.value('text()[1]','int') as IdCliente
from     @xmlCliente.nodes('//id') as t(c)




@xmlCliente es la variable que contiene la cadena del XML.

Observa que 'text()[1]' es utilizado para leer el valor de los elementos de este XML
En este ejemplo se está accediendo directamente a los nodos <id>   =>  '//id'




Ejemplo completo:

El xml en cadena se asigna a una variable de tipo XML:

DECLARE @xmlCliente as xml
set @xmlcliente =
'<cliente>
  <id>57</id>
  <id>58</id>
  <id>59</id>
</cliente>';
  SELECT t.c.value('text()[1]','int') as IdCliente
from @xmlCliente.nodes('//id') as t(c)

     = >  







EJEMPLO 2


Ahora bien, si dentro de tu XML tienes atributos y deseas leerlos,
se hace  de la siguiente manera:

1.-  Cuando el Atributo esta en el elemento padre, entonces debemos subir al nodo un nivel,
     ya que el ejemplo anterior se colocó directamente en el nodo <Id>.

<cliente name="Juanito Perez">
  <id>57</id>
  <id>58</id>
  <id>59</id>
</cliente>


Se selecciona el nodo del elemento principal <cliente>
con un alias nombre tabla y nombre columna
y de ese mismo nodo principal, ahora en lugar de seleccionar el contenido
del elemento (con 'text()') ahora seleccionamos el valor del atributo 'name'
colocando una @ para atributos.

SELECT                     
             t.c.value('@name[1]','varchar(20)') as Nombre
            ,t2.c2.value('text()[1]','int') as Id
from         @xmlCliente.nodes('//cliente') as t(c)
cross apply  t.c.nodes('id') as t2(c2)

Para acceder al valor de los elementos, se debe obtener del nodo principal
t.c.nodes, el cual realizamos un cross apply...





EJEMPLO COMPLETO:

DECLARE @xmlCliente as xml
SET @xmlcliente =
'
<cliente name="Juanito Perez">
  <id>57</id>
  <id>58</id>
  <id>59</id>
</cliente>
';

 SELECT
                     
             t.c.value('@name[1]','varchar(20)') as Nombre
             ,t2.c2.value('text()[1]','int') as Id
from         @xmlCliente.nodes('//cliente') as t(c)
cross apply  t.c.nodes('id') as t2(c2)




2.- Cuando los elementos secundarios contiene atributos:

<cliente name="Juanito Perez">
  <id value="A"> 57 </id>
  <id value="B"> 58 </id>
  <id value="C"> 59 </id>
</cliente>

Solo resta agregar la columna como atributo '@' ya que esos
elementos se tienen en t2(c2)

,t2.c2.value('@value[1]','varchar(1)') as value












EJEMPLO COMPLETO:

DECLARE @xmlCliente as xml
set @xmlcliente =
'
<cliente name="Juanito Perez">
  <id value ="A" > 57 </id>
  <id value ="B" > 58 </id>
  <id value ="C" > 59 </id>
</cliente>
';

 SELECT
                     
              t.c.value('@name[1]','varchar(20)') as Nombre
             ,t2.c2.value('text()[1]','int') as Id
             ,t2.c2.value('@value[1]','varchar(1)') as value
from         @xmlCliente.nodes('//cliente') as t(c)
cross apply  t.c.nodes('id') as t2(c2)

=>


Entonces concluimos que el contenido
de un elemento se obtiene con 'text()[1]' 
y el valor de un atributo con el prefijo '@










XML con namespaces

DECLARE @xmlCliente as xml
SET @xmlcliente =
'
<ns:cliente name="Juanito Perez"  xmlns:ns="http://google.com" >
  <ns:id>57</ns:id>
  <ns:id>58</ns:id>
  <ns:id>59</ns:id>
</ns:cliente>
';
WITH XMLNAMESPACES ( 'http://google.com' as "ns" )
 SELECT
                    
             t.c.value('@name[1]','varchar(20)') as Nombre
             ,t2.c2.value('text()[1]','int') as Id
from         @xmlCliente.nodes('//ns:cliente') as t(c)
cross apply  t.c.nodes('ns:id') as t2(c2)










<Basket xmlns="http://tempuri.org/basketDayArchives.xsd">
  <BasketList data="2003-01-02" val="30.05"> 1 </BasketList>
  <BasketList data="2003-01-03" val="30.83"> 2 </BasketList>
  <BasketList data="2003-01-06" val="30.71"> 3 </BasketList>
</Basket>
 

 
;WITH XMLNAMESPACES
                  (
                   'http://tempuri.org/basketDayArchives.xsd' AS ns
                  )
                    SELECT
                           y.value (N'@val   [1]', N'varchar(100)')     AS Valor
                          ,y.value (N'@data  [1]', N'varchar(100)')     AS Fecha
                          ,y.value (N'text() [1]', N'varchar(100)')     AS valorElemento
 
                    FROM @XML.nodes(N'//ns:Basket') t(c)
                    OUTER APPLY c.nodes ('ns:BasketList') as r(y)         
 
                   select @XML







PIVOT SQL

----------------------------------- PIVOT
A continuación se presenta una serie de ejemplos para la utilización de PIVOT en SQL Server.
Para ir comprendiendo de manera más fácil, iré realizando ejemplos muy sencillos pero prácticos.


BASE: Se construye una tabla que nos apoyará en el ejemplo


DECLARE @Tabla as table (EnglishDayName varchar (15), Qty smallint)

insert into @Tabla
select 'Saturday' , 54     union all
select 'Wednesday', 15     union all
select 'Monday',    98     union all
select 'Sunday',    45     union all
select 'Friday',    33     union all
select 'Thursday',  1      union all
select 'Tuesday',   450


---------- Listo, ya tenemos nuestra tabla para el ejemplo
select * from @Tabla




Para llamar al operador PIVOT, debe mandar llamar una agregación (SUM, AVG, COUNT etc) necesaria en cualquier valor de columna.

1.- para el siguiente ejemplo se tiene una función de agregación SUM
2.- FOR: Columna que contiene los valores que se convertirán en encabezados de columna
3.- IN [Columna Dinamizada] --  (contenido de la Columna)
4.- Por último deje un nombre de alias al PIVOT 

SELECT *
FROM   @Tabla
PIVOT  
        (
             SUM(Qty) FOR EnglishDayName IN [Sunday],[Monday],[Tuesday],[wednesday],                                                                                           [Thursday],[Friday],[Saturday] )
        ) AS PV


  Resultado:







EJEMPLO 2:


Para el ejemplo dos, voy a agregar otra columna más a la tabla:

DECLARE @Tabla as table ([Year] int, EnglishDayName varchar (15), Qty smallint)

insert into @Tabla
select 2015, 'Saturday' ,  54     union all
select 2015, 'Wednesday',  15     union all
select 2015, 'Monday',     98     union all
select 2015, 'Sunday',     45     union all
select 2015, 'Friday',     33     union all
select 2015, 'Thursday',   1      union all
select 2015, 'Tuesday',    450    union all
select 2014, 'Saturday' ,  9      union all
select 2014, 'Wednesday',  71     union all
select 2014, 'Monday',     98     union all
select 2014, 'Sunday',     88     union all
select 2014, 'Friday',     73     union all
select 2014, 'Thursday',   10     union all
select 2014, 'Tuesday',    45



select * from @Tabla



select *
from   @Tabla
PIVOT  
        (
             SUM(Qty) FOR [YEAR] IN ([2015],[2014])

        ) AS PV


Resultado:


ó se puede hacer de la siguiente manera




select *
from   @Tabla
PIVOT  
        (
             SUM(Qty) FOR EnglishDayName IN ( [Sunday],[Monday],[Tuesday],[Wednesday],[Thursday],[Friday],[Saturday] )

        ) AS PV

Resultado:

























EJEMPLO 3

DECLARE @Table as TABLE (Client varchar(20), Product varchar(20), Qty tinyint)

insert into @Table
select 'John' ,'bike' , 1         union all
select 'John' ,'moto' , 3         union all
select 'Karen','moto' , 5         union all
select 'Karen','bike' , 7         union all
select 'John' ,'bike' , 4         union all
select 'Karen','car'  , 1         union all
select 'Karen','moto' , 9         union all
select 'Karen','bike' , 3         union all
select 'Karen','moto' , 2         union all
select 'John' ,'moto' , 4

select * from @Table


Tabla para el ejemplo:
















PIVOT: 

Select *
from   @Table
  PIVOT
       (
              SUM(Qty) FOR Product IN ( [bike], [moto], [car])

           ) AS PV

Result: