For XML as PIVOT - sql

Thanks for reading.
I need to export data via SQL to XML. But I need the XML format in Row/column and the output must be a Pivot table. I know that it can be done with AS pivot. But I don't know how to use it in the below script
I've already got a fantastic script with the outcome in Row/Column format, but the output must be in pivot
;With CTE
AS
(
SELECT [Name]
,[ColumnA]
,[ColumnB]
,[ColumnC]
FROM Fact_A INNER JOIN Dim_A on
Fact_A.Column_Key = Dim_A.Column_Key
)
select
(
select [Name] AS [#name],
(select [ColumnA] as [column],
null as tmp,
ColumnB as [column],
null as tmp,
ColumnC as [column]
from CTE
where [Name] = t.[Name]
for xml path('row'),type) as [*]
from (select distinct [Name] from CTE)t
for xml path('variable'),root('data')
) as col_xml
the above query needs to be in the same XML format(Row/Clolumn) but then in a Pivot table structure.
The desired outcome:
........CellA...CellB
companyA..4.......3
companyB..0.......4
companyC..1.......2
(whithout the ..............)
The desired outcome in XML:
<data>
<variable name="Name">
<row>
<column></column>
<column>A</column>
<column>B</column>
</row>
<row>
<column>companyA</column>
<column>4</column>
<column>3</column>
</row>
<row>
<column>companyB</column>
<column>0</column>
<column>4</column>
</row>
<row>
<column>companyC</column>
<column>1</column>
<column>2</column>
</row>
</variable>
Is this possible?
Thanks in advance.
Regards,
Bart

;With CTE
AS
(
SELECT [Name]
,[ColumnA]
,[ColumnB]
,[ColumnC]
FROM Fact_A
INNER JOIN Dim_A on
Fact_A.Column_Key = Dim_A.Column_Key
) , pvtClust as
(
select [Name], [ColumnA],
[A], [B]
from CTE
pivot (Sum(ColumnA) for
[Name] in ([A], [B])) pvt
)
select
(
select [Name] AS [#name],
(SELECT '' as [column]
, null as [tmp]
,'A' as [column]
, null as [tmp]
, 'B' as [column]
for xml path ('row'), type) as [*],
(select [Name] as [column],
null as tmp,
ISNULL([A], 0) as [column],
null as tmp,
ISNULL([B], 0) as [column]
from pvtClust
where [Name] = t.[Name]
for xml path('row'),type) as [*]
from (select distinct [Name] from CTE) t
for xml path('variable'),root('data')
) as col_xml
Credits to:
Russel Loski, MCT, MCSE Data Platform/Business Intelligence. Twitter: #sqlmovers; blog: www.sqlmovers.com

Related

Import xml data in SQL Server 2017

I have XML data like this:
<?xml version="1.0" ?>
<SettlementFile>
<Transaction>
<Identifier>
<StationID>049215901 </StationID>
<TransactionTimestamp>2021-04-01T10:39:32</TransactionTimestamp>
</Identifier>
<TerminalInfo>
<TerminalID>21590151</TerminalID>
<TerminalType>2</TerminalType>
</TerminalInfo>
<TransactionInfo>
<TransactionType>0</TransactionType>
<TransactionAmount>3.74</TransactionAmount>
<CurrencyCode>978</CurrencyCode>
<CustomerInput>
<Mileage>0</Mileage>
</CustomerInput>
<TicketNumber>213510037</TicketNumber>
<AuthorisationType>1</AuthorisationType>
</TransactionInfo>
</Transaction>
</SettlementFile>
My SQL Server table structure:
CREATE TABLE dbo.Import_Oase
(
StationID varchar(50) NULL,
TransactionTimestamp datetime NULL,
TicketNumber int NULL,
Mileage varchar(50) NULL
) ON PRIMARY
I'm trying to use this SELECT query:
SELECT
MY_XML.Details.query('StationID') .value('.', 'VARCHAR(50)'),
MY_XML.Details.query('TransactionTimestamp').value('.', 'Datetime'),
MY_XML.Details.query('TicketNumber') .value('.', 'Integer'),
MY_XML.Details.query('Mileage') .value('.', 'VARCHAR(50)')
FROM
(SELECT
CAST(MY_XML AS XML)
FROM
OPENROWSET(BULK '\\EO-TEST\SQL-Daten\Temp\MY_XML.xml', SINGLE_BLOB) AS T(MY_XML)
) AS T(MY_XML)
CROSS APPLY
MY_XML.nodes('SettlementFile/Transaction/Identifier, SettlementFile/Transaction/TransactionInfo, SettlementFile/Transaction/TransactionInfo/CustomerInput') AS MY_XML (Details);
I need to get the result in one line because it is all for 1 transactions. But it is in three different line in SQL.
Please try the following solution.
When you are satisfied with the outcome, just uncomment the INSERT INTO line.
SQL
WITH rs (xmlData) AS
(
SELECT TRY_CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK N'e:\Temp\ daryosmitan.xml', SINGLE_BLOB) AS x
)
-- INSERT INTO dbo.Import_Oase (StationID, TransactionTimestamp, TicketNumber, Mileage)
SELECT c.value('(Identifier/StationID/text())[1]', 'VARCHAR(50)') AS StationID
, c.value('(Identifier/TransactionTimestamp/text())[1]', 'DATETIME') AS TransactionTimestamp
, c.value('(TransactionInfo/TicketNumber/text())[1]', 'VARCHAR(50)') AS TicketNumber
, c.value('(TransactionInfo/CustomerInput/Mileage/text())[1]', 'INT') AS Mileage
FROM rs
CROSS APPLY xmlData.nodes('/SettlementFile/Transaction') AS t(c);

How can I set the xml result to the nvarchar declaration in sql

I have the following sql , what I want is the return of the select to be assigned to the #NewCor Nvarchar , but I can't make it work
declare #NewCor nvarchar(max)
select
(select 'ID' as th for xml path(''), type),
(select 'Cod' as th for xml path(''), type),
(select 'Nume' as th for xml path(''), type)
union all
select
(select p.id as 'td' for xml path(''), type),
(select p.cod as 'td' for xml path(''), type),
(select p.nume as 'td' for xml path(''), type)
from #TempCor p
for xml path('tr')
I am so sure about the internal structure of your temp table, so you may need to tweak a few things to match your use case. But generally this should give you an idea of how to do that:
declare #NewCor nvarchar(max);
select CONVERT(xml, N'<table><tr><th>a</th><th>Cod</th><th>Nume</th></tr><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>1</td><td>2</td><td>3</td></tr></table>') [type] into #TempCor;
;with [base] as (
select top 1
T.TR.value(N'(th)[1]', N'nvarchar(max)') as [1],
T.TR.value(N'(th)[2]', N'nvarchar(max)') as [2],
T.TR.value(N'(th)[3]', N'nvarchar(max)') as [3],
0 [Order]
from [#TempCor] [p]
cross apply [p].[type].nodes(N'(/table/tr)') [T](TR)
union all
select
T.TR.value(N'(td)[1]', N'nvarchar(max)'),
T.TR.value(N'(td)[2]', N'nvarchar(max)'),
T.TR.value(N'(td)[3]', N'nvarchar(max)'),
ROW_NUMBER() OVER(ORDER BY GETDATE())
from [#TempCor] [p]
cross apply [p].[type].nodes(N'(/table/tr)') [T](TR)
where
T.TR.value(N'(td)[1]', N'nvarchar(max)') is not NULL or
T.TR.value(N'(td)[2]', N'nvarchar(max)') is not NULL or
T.TR.value(N'(td)[3]', N'nvarchar(max)') is not NULL
), [rec] as (
select N'<tr><th>'+[1]+N'</th><th>'+[2]+N'</th><th>'+[3]+N'</th></tr>' as [string], [Order]
from [base]
where [Order] = 0
union all
select [rec].[string]+N'<tr><td>'+[1]+N'</td><td>'+[2]+N'</td><td>'+[3]+N'</td></tr>', [base].[Order]
from [rec] join [base] on [base].[Order] = [rec].[Order] + 1
)
select #NewCor=[string]
from [rec]
where [Order] = (select MAX([Order]) from [base]);
Basically:
Extract the data from XML, so you get a normal SQL table
The recursively combine the data
Finally: Assign the outcome (which is where Order is maxed) to a variable

Read XML data in SQL Server 2012

I want to read xml data in the xml file.
I have a table column consist with the xml data.
if i click on the xml file it will open in the Sql server Management studio.
xml file format shown below.
I want to read only NTDomainName, DatabaseName and ServerName and write that data in the another Table. Table format shown below
NTDomainName | DatabaseName | ServerName
----------
ABC | TestCube1 | SERXYZ
Try this:
declare #xml xml
set #xml = '<event><data name="NTUserName"><value>MyName</value></data><data name="NTDomainName"><value>DomainName</value></data><data name="ServerName"><value>ServerName</value></data></event>'
select [NTDomainName], [DatabaseName], [ServerName] from
(
select [name],[value] from (
select c.value('./#name', 'varchar(100)') [name], c.value('(./value)[1]', 'varchar(100)') [value]
from #xml.nodes('/event/data') as t(c)
) a where [name] in ('NTDomainName', 'DatabaseName', 'ServerName')
) x
pivot (
max(value) for [name] in ([NTDomainName], [DatabaseName], [ServerName])
) as [pivot_Name]
The most inner query will retrieve information from XML, one row for every name attribute value, that you want to retrieve. So, output of this query needs to be pivoted.
i think you look for this:
SELECT * FROM (
SELECT
CAST(f.x.query('data(#name)') as varchar(150)) as data_name,
CAST(f.x.query('data(value)') as varchar(150)) as data_value
FROM #xml.nodes('/event') as t(n)
CROSS APPLY t.n.nodes('data') as f(x)) X
PIVOT (MAX(data_value) FOR data_name IN (NTDomainName, DatabaseName, ServerName)) as pvt
If you do not want to use PIVOT:
DECLARE #DataSource TABLE
(
[ID] TINYINT IDENTITY(1,1)
,[XML] XML
);
INSERT INTO #DataSource ([XML])
VALUES ('<event><data name="SessionID">S1</data><data name="NTUserName">User1</data><data name="DatabaseName">DB1</data><data name="ServerName">SN1</data></event>')
,('<event><data name="SessionID">S1</data><data name="NTUserName">User2</data><data name="DatabaseName">DB2</data><data name="ServerName">SN2</data></event>');
SELECT [ID]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'NTUserName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [NTUserName]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'DatabaseName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [DatabaseName]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'ServerName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [ServerName]
FROM #DataSource
CROSS APPLY [XML].nodes('event/data[#name = "NTUserName" or #name = "DatabaseName" or #name = "ServerName"]') T(c)
GROUP BY [ID];

Putting the column type from the DB to a XML attribute

Doing the following query:
SELECT * FROM MY_DATA
FOR XML PATH('NODE'), TYPE, ROOT('ROOT')
I have the following output:
<ROOT>
<NODE>
<THE_ID>11</Facility_ID>
<Station_ID>HA</Station_ID>
<Case_No>731</Case_No>
</NODE>
</ROOT>
What I'm wondering is whether is possible to have an output like the following:
<ROOT>
<NODE>
<THE_ID int>11</Facility_ID>
<Station_ID varchar="30">HA</Station_ID>
<Case_No varchar="50>731</Case_No>
</NODE>
</ROOT>
With the types as attributes.
Is it possible?
Thank you in advance.
Here's the information you're after. Tie it into your query and play with.
To get an item as an attribute, use "as [#AttributeName]".
For instance in your example change the Select Station_Id portion to Select a, b, Station_Id as [#Station_Id].
'
DECLARE #Table VARCHAR(MAX) = 'YourTableName'
SELECT t.name AS [Table]
, c.name AS [Column]
, TYPE_NAME(c.user_type_id) AS [Type]
, c.max_length AS [Size]
, CASE WHEN c.is_nullable = 1 THEN ''
ELSE 'No Nulls'
END AS Nullable
, ROW_NUMBER() OVER ( PARTITION BY t.name ORDER BY c.name ASC ) AS rnk
FROM sys.columns AS c
JOIN sys.tables AS t ON c.object_id = t.object_id
WHERE t.name LIKE #Table
-- AND c.name IN ( 'thiscol', 'thatcol' )
ORDER BY t.name
, c.name

How to Generate xml from sql for below pattern

I'm writing one stored procedure, which I have to create a xml column from db.
µ = CHAR(181) this is value separator,
¶ = CHAR(182) this is row separator
This is the statement I wrote. I know its not well formed.
SELECT #xmlString= CAST('<root><Section> ID =' + REPLACE(REPLACE ('20211µ1¶20212µ2', CHAR(182),
'</Section><Section> ID ='),CHAR(181), ' Slno=') + '</Section></root>' AS XML)
This is the pattern which I need to display like this.
<root>
<sections id="20211" slno="1" ></sections>
<sections id="20215" slno="2" ></sections>
</root>
declare #s varchar(50) = '20211µ1¶20212µ2'
declare #xmlString xml
;with C as
(
select T.N.value('value[1]', 'int') as id,
T.N.value('value[2]', 'int') as slno
from (select cast('<item><value>'+replace(replace(#s, 'µ','</value><value>'), '¶','</value></item><item><value>')+'</value></item>' as xml)) as X(XMLCol)
cross apply X.XMLCol.nodes('item') as T(N)
)
select #xmlString =
(
select C.id as [#id] ,
C.slno as [#slno]
from C
for xml path('sections'), root('root'), type
)
select #xmlString
Result:
<root>
<sections id="20211" slno="1" />
<sections id="20212" slno="2" />
</root>