Table Name : sample
Column Name : id,name
Every Row Create Separate tag with inside.
Show the Xml value like this
<Details>
<id>1</id>
<name>na</name>
<Details>
<id>2</id>
<name>aa</name>
</Details>
</Details>
I tried like this but its not working
select
id 'Details\id'
,name 'Details\name'
from sample
How do get that xml output?
It is hardcoded but should work:
DECLARE #x xml
SELECT #x = (
SELECT x+''
FROM (
SELECT '%details?%id?'+CAST(id as nvarchar(max))+'%/id?%name?'+name+'%/name?' x
FROM [sample] s
UNION ALL
SELECT '%/details?'
FROM [sample] s
) as t
FOR XML PATH('')
)
SELECT CAST(REPLACE(REPLACE((CAST(#x as nvarchar(max))),'%','<'),'?','>') as xml)
In [sample] table I got:
(1,'na'),
(2,'aa'),
(3,'sd')
Output:
<details>
<id>1</id>
<name>na</name>
<details>
<id>2</id>
<name>aa</name>
<details>
<id>3</id>
<name>sd</name>
</details>
</details>
</details>
EDIT
Also it could be done with recursive CTE:
DECLARE #x xml
;WITH rec AS (
SELECT CAST((
SELECT TOP 1 id,
[name]
FROM [sample]
ORDER BY id DESC
FOR XML PATH('details')
) as xml) as d,
1 as [Level]
UNION ALL
SELECT CAST((
SELECT id,
[name],
cast(r.d as xml)
FROM [sample]
WHERE s.id = id
FOR XML PATH('details')
) as xml) as d,
r.[Level]+1
FROM [sample] s
INNER JOIN rec r
ON s.id = CAST(r.d.query('/details/id/text()') as nvarchar(max))-1
)
SELECT TOP 1 WITH TIES d
FROM rec
ORDER BY [Level] desc
Same output.
You can use query like this:
SELECT
*,
(SELECT
*
FROM #details
WHERE id = 2
FOR xml PATH ('Details'), TYPE)
FROM #details
WHERE id = 1
FOR xml PATH ('Details')
For inner loop you can use CTE
Table creation scripts :
CREATE TABLE #details (
id int,
name varchar(10)
)
INSERT INTO #details (id, name)
VALUES (1, 'test'), (2, 'test2')
Related
Lets say I have table T with one column A.
What I would like to achieve as result is xml like this :
<not>
<mes>not important what include</mes>
<A>1</A>
<A>2</A>
<A>3</A>
<A>4</A>
...
</not>
Was trying something similar to :
SELECT
'important' AS [mes],
(select A as [A] from T)- of course that part is incorrect but don't know how to handle it
FROM T2
FOR XML PATH ('not');
Please advice.
Updated QUERY
SET #SQL = '
WITH XMLNAMESPACES (''https://something..'' as ns)
SELECT
Q.DocumentType AS [#type],
Q.ReferenceNo AS [#ref],
Q.Id AS [#id],
D.DocId AS [#docId],
N.NotId AS [#notId],
CONVERT(char(10), N.CreationDate, 126) AS [#notdate],
''mes'' AS [mes/#content],
#mes2 AS [mes/content],
[mes] = ''important'' ,
(select A from '+ Cast(#TableName as VARCHAR(60))+' FOR XML PATH (''''), type)
FROM
[DB].[dbo].[tab1] AS Q
LEFT JOIN [DB].[dbo].[tab2] AS D ON Q.ID=D.ID
LEFT JOIN [DB].[dbo].[tab3] AS N ON D.ID=N.DocId
WHERE
Q.ID='+ Cast(#Id as varchar(15))+'
FOR XML PATH (''not'')';
execute (#SQL);
Perhaps this will help
-- Just a DEMONSTRATIVE Table Variable
--------------------------------------------
Declare #YourTable Table ([A] varchar(50))
Insert Into #YourTable Values
(1)
,(2)
,(3)
,(4)
SELECT [mes] = 'important'
,( Select A from #YourTable For XML Path(''),type )
FOR XML PATH ('not');
Results
<not>
<mes>important</mes>
<A>1</A>
<A>2</A>
<A>3</A>
<A>4</A>
</not>
SELECT
CASE WHEN D.DocumentCode='SA' THEN D.Name END AS 'IDProofofsigningauthority',
CASE WHEN D.DocumentCode='GSTIN' THEN D.Name END AS 'GSTINRegistrationCopy',
CASE WHEN D.DocumentCode='SA_T' OR D.DocumentCode='SA_E' THEN D.Name END AS 'IDProofofsigningauthority',
CASE WHEN D.DocumentCode='PAN_T' THEN D.Name END AS 'PANCard',
CONCAT ('https://abc/xyz/',"Filename") AS KYCDocumentUrl,
CASE WHEN D.DocumentCode='GSTIN' THEN BPD.DocumentNumber END AS 'GSTINRegistrationCopyDocumentNumber',
CASE WHEN D.DocumentCode='PAN_T' THEN BPD.DocumentNumber END AS 'PANCardDocumentNumber'
FROM
[dbo].[Documents] D
INNER JOIN
[dbo].[BusinessPartyDcoument] BPD WITH (NOLOCK) ON D.Id = BPD.DocumentId
FOR XML PATH('Document')
This is my current output:
<Document>
<GSTINRegistrationCopy>GSTIN Number</GSTINRegistrationCopy>
<KYCDocumentUrl>https://abc/xyz/R1NUSU5fMTEy.pdf</KYCDocumentUrl>
<GSTINRegistrationCopyNumber>1111</GSTINRegistrationCopyNumber>
</Document>
<Document>
<PANCard>PAN Card</PANCard>
<KYCDocumentUrl>https://abc/xyz/UEFOX1RfNjFfOC8yLzIwMTkgN.pdf</KYCDocumentUrl>
<PANCardDocumentNumber>BBBBB1111V</PANCardDocumentNumber>
</Document>
<Document>
<IDProofauthority>ID Proof of signing authority</IDProofauthority>
<KYCDocumentUrl>https://abc/xyz/U0FfNjFfOC8yLzIwMTkgNjo1.pdf</KYCDocumentUrl>
</Document>
This is my desired output:
<GSTINRegistrationCopy>
<DocumentName>GSTIN Number</DocumentName>
<KYCDocumentUrl>https://abc/xyz/R1NUSU5fMTEy.pdf</KYCDocumentUrl>
<DocumentNumber>1111</DocumentNumber>
</GSTINRegistrationCopy>
<PANCard>
<DocumentName>PAN Card</DocumentName>
<KYCDocumentUrl>https://abc/xyz/UEFOX1RfNjFfOC8yLzIwMTkgN.pdf</KYCDocumentUrl>
<DocumentNumber>BBBBB1111V</DocumentNumber>
</PANCard>
<IDProofauthority>
<DocumentName>ID Proof of signing authority</DocumentName>
<KYCDocumentUrl>https://abc/xyz/U0FfNjFfOC8yLzIwMTkgNjo1.pdf</KYCDocumentUrl>
</IDProofauthority>
I need to get document name instead of <Document> tag as shown in the output using SQL Server query. I need to get expected XML output using my query.
Please suggest how to get this done.
Actually, you want nested xml for each "case" in you "case when".
You can use "for xml path" and "for xml path, type" in nested queries.
But this solution has obvious problems with performance, you can't use it for big amounts of data
declare #Document table
(
DocumentCode varchar(10),
Name varchar(100),
filename varchar(100),
DocumentNumber varchar(20)
)
insert into #document values
('PAN_T','PAN Card','UEFOX1RfNjFfOC8yLzIwMTkgN.pdf','BBBBB1111V'),
('GSTIN','GSTIN Number','R1NUSU5fMTEy.pdf','1111'),
('SA','D Proof of signing authority','U0FfNjFfOC8yLzIwMTkgNjo1.pdf',NULL);
SELECT
CASE WHEN D.DocumentCode='GSTIN' THEN
(
select D.Name 'DocumentName',
'https://abc/xyz/'+d.Filename 'KYCDocumentUrl',
D.DocumentNumber 'DocumentNumber'
for xml path('') ,type
) END GSTINRegistrationCopy
,CASE WHEN D.DocumentCode='PAN_T' THEN
(
select D.Name 'PANCard',
'https://abc/xyz/'+d.Filename 'KYCDocumentUrl',
D.DocumentNumber 'DocumentNumber'
for xml path('') ,type
) END PANCard
,CASE WHEN D.DocumentCode='SA' THEN
(
select D.Name 'DocumentName',
'https://abc/xyz/'+d.Filename 'KYCDocumentUrl'
for xml path('') ,type
) END IDProofauthority
FROM
#Document D
FOR XML PATH('')
(Similar to vitalygolub's answer...)
Given source data structured like the OPs:
if object_id('[dbo].[Documents]') is not null drop table [dbo].[Documents];
if object_id('[dbo].[BusinessPartyDcoument]') is not null drop table [dbo].[BusinessPartyDcoument];
select * into [dbo].[Documents]
from (values
(1, 'GSTIN', 'GSTIN Number'),
(2, 'PAN_T', 'PAN Card'),
(3, 'SA', 'ID Proof of signing authority')
) Src ([Id], [DocumentCode], [Name]);
select * into [dbo].[BusinessPartyDcoument]
from (values
(1, 'R1NUSU5fMTEy.pdf', '1111'),
(2, 'UEFOX1RfNjFfOC8yLzIwMTkgN.pdf', 'BBBBB1111V'),
(3, 'U0FfNjFfOC8yLzIwMTkgNjo1.pdf', null)
) Src ([DocumentId], [Filename], [DocumentNumber]);
The following SQL:
SELECT
(
SELECT
D.Name AS 'DocumentName',
DocumentUrl AS 'KYCDocumentUrl',
BPD.DocumentNumber AS 'DocumentNumber'
WHERE D.DocumentCode='GSTIN'
FOR XML PATH('GSTINRegistrationCopy'), TYPE
),
(
SELECT
D.Name AS 'DocumentName',
DocumentUrl AS 'KYCDocumentUrl',
BPD.DocumentNumber AS 'DocumentNumber'
WHERE D.DocumentCode='PAN_T'
FOR XML PATH('PANCard'), TYPE
),
(
SELECT
D.Name AS 'DocumentName',
DocumentUrl AS 'KYCDocumentUrl'
WHERE D.DocumentCode='SA'
FOR XML PATH('IDProofofsigningauthority'), TYPE
)
FROM
[dbo].[Documents] D
INNER JOIN
[dbo].[BusinessPartyDcoument] BPD WITH (NOLOCK) ON D.Id = BPD.DocumentId
OUTER APPLY (
SELECT DocumentUrl = CONCAT('https://abc/xyz/', "Filename")
) DU
FOR XML PATH('');
Outputs the following XML:
<GSTINRegistrationCopy>
<DocumentName>GSTIN Number</DocumentName>
<KYCDocumentUrl>https://abc/xyz/R1NUSU5fMTEy.pdf</KYCDocumentUrl>
<DocumentNumber>1111</DocumentNumber>
</GSTINRegistrationCopy>
<PANCard>
<DocumentName>PAN Card</DocumentName>
<KYCDocumentUrl>https://abc/xyz/UEFOX1RfNjFfOC8yLzIwMTkgN.pdf</KYCDocumentUrl>
<DocumentNumber>BBBBB1111V</DocumentNumber>
</PANCard>
<IDProofofsigningauthority>
<DocumentName>ID Proof of signing authority</DocumentName>
<KYCDocumentUrl>https://abc/xyz/U0FfNjFfOC8yLzIwMTkgNjo1.pdf</KYCDocumentUrl>
</IDProofofsigningauthority>
I have table that contains three columns:
[ID],[Name],[Value]
My select for xml result:
DECLARE #xml XML
SET #xml = (
SELECT
ID
,[Name]
,[Value]
FROM [CustomerDetails]
WHERE ID = 1
FOR XML PATH(''), ROOT('Customer')
)
SELECT #xml
My select return xml with multiple ID properties:
<Customer>
<ID>1</ID>
<Name>FirstName</Name>
<Value>firstName</Value>
<ID>1</ID>
<Name>LastName</Name>
<Value>lastName</Value>
<ID>1</ID>
<Name>Age</Name>
<Value>20</Value>
<ID>1</ID>
<Name>City</Name>
<Value>London</Value>
</Customer>
I need next xml:
<Customer>
<ID>1</ID>
<Name>FirstName</Name>
<Value>firstName</Value>
<Name>LastName</Name>
<Value>lastName</Value>
<Name>Age</Name>
<Value>20</Value>
<Name>City</Name>
<Value>London</Value>
</Customer>
How to return this kind of XML?
I have shortened name of columns:
declare #id int = 1
select id, n, v from
(select #id id, null n, null v, 1 as rn from t
union
select null, n, v, 2 as rn from t
where id = #id
) t order by rn
for xml path(''), root('customer')
Output:
<customer><id>1</id><n>n1</n><v>v1</v><n>n2</n><v>v2</v><n>n3</n><v>v3</v></customer>
Fiddle http://sqlfiddle.com/#!3/70ea0/4
I am using SSMS 2008 with the following query:
DECLARE #TestData TABLE
(
address_desc NVARCHAR(100) NULL
,people_id UNIQUEIDENTIFIER NULL
);
INSERT #TestData
SELECT a.address_desc, a.people_id
FROM dbo.address_view a
SELECT a.people_id,
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM #TestData b
WHERE a.people_id = b.people_id
FOR XML PATH(''))
,2
,4000)
) GROUP_CONCATENATE
FROM #TestData a
GROUP BY a.people_id
This query works, but I want to make this into a view or function so that I can call it from different stored procs. How can I do this? From what I understand, variables cannot be declared in VIEW statements.
Hong, here is my updated query based on your advice which gives me errors:
DECLARE #TestData TABLE
(
address_desc NVARCHAR(100) NULL
,people_id UNIQUEIDENTIFIER NULL
);
INSERT #TestData
SELECT a.address_desc, a.people_id FROM dbo.address_view a
SELECT a.people_id,
(SELECT address_desc, people_id FROM dbo.address_view),
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM #TestData b
WHERE a.people_id = b.people_id
FOR XML PATH(''))
,2
,4000)
) GROUP_CONCATENATE
FROM #TestData a
GROUP BY a.people_id
In your last select query replace #TestData with subquery (SELECT address_desc, people_id FROM dbo.address_view), and then get rid of temp table #TestData.
Try this:
Create View YourView As
SELECT a.people_id,
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM (SELECT address_desc, people_id FROM dbo.address_view) b
WHERE a.people_id = b.people_id
FOR XML PATH(''))
,2
,4000)
) GROUP_CONCATENATE
FROM (SELECT address_desc, people_id FROM dbo.address_view) a
GROUP BY a.people_id
I'm rather experienced with SQL server "select for XML path" queries but now i run into a strange problem.
The following query works fine:
select
(
select
'Keyfield1' as "#Name",
t1.Keyfield1 as "Value"
from MyTable t1
where
t1.KeyField1= t2.KeyField1 and
t1.KeyField2= t2.KeyField2
for xml path('Field'),type, elements
) as 'Key'
from MyTable t2
for XML path('Path') , elements XSINIL, root('Root')
This will result (for a dummy dataset) in this XML:
<Root>
<Path>
<Key Name="KeyField1">
<Value>DummyValue1</Value>
</Key>
</Path>
</Root>
In my result of this (part of a bigger) statement i need the 2nd keyfield too:
<Root>
<Path>
<Key Name="KeyField1">
<Value>DummyValue1</Value>
</Key>
<Key Name="KeyField2">
<Value>DummyValue2</Value>
</Key>
</Path>
</Root>
So i changed my (sub)query with a union-select to:
select
(
select
'Keyfield1' as "#Name",
t1.Keyfield1 as "Value"
union all
select
'Keyfield2' as "#Name",
t1.Keyfield2 as "Value"
from MyTable t1
where
t1.KeyField1= t2.KeyField1 and
t1.KeyField2= t2.KeyField2
for xml path('Field'),type, elements
) as 'Key'
from MyTable t2
for XML path('Path') , elements XSINIL, root('Root')
But now i get the error "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."
I know it is possible to have multiple records in a subquery with for XML path witch results in multiple elements. But i don't understand why this can't be done with a union.
Can someone put me in the right direction how to accomplisch the XML with the 2 keyfields in my (sub)query?
Thanx you very much.
The problem with your subselect is that the first part isn't referring to any table at all (no FROM-clause).
This listing gives me the output you requested:
declare #mytable table (
keyfield1 nvarchar(20),
keyfield2 nvarchar(20)
)
insert into #mytable values ('Dummyvalue1', 'Dummyvalue2')
select * from #mytable
select
(
select
'Keyfield1' as "#Name",
t1.Keyfield1 as "Value"
from #mytable t1
where
t1.KeyField1= t2.KeyField1 and
t1.KeyField2= t2.KeyField2
for xml path('Field'),type, elements
) as 'Key'
from #mytable t2
for XML path('Path') , elements XSINIL, root('Root')
select
(
select * from (
select
'Keyfield1' as "#Name",
t1.Keyfield1 as "Value"
from #MyTable t1
where
t1.KeyField1= t2.KeyField1
union all
select
'Keyfield2' as "#Name",
t3.Keyfield2 as "Value"
from #MyTable t3
where
t3.KeyField2= t2.KeyField2) a
for xml path('Field'),type, elements
) as 'Key'
from #MyTable t2
for XML path('Path') , elements XSINIL, root('Root')
Here is a simplified example, but does this get you what you need?
select
(
select
'Keyfield1' as "#Name",
'Blah' as "Value"
for xml path('Key'),type, elements
),
(
select
'Keyfield2' as "#Name",
'Blah' as "Value"
for xml path('Key'),type, elements
)
for XML path('Path') , elements XSINIL, root('Root')