Select query from XML data - sql

I am trying to get result from XML data but only getting a value of first node.
create table #temp(xmlString nvarchar(max))
insert into #temp (xmlString) values
('<?xml version="1.0" ?><response status = "ERROR">
<error>Error1</error>
<error>Error2</error>
</response>')
I want a result :
Error1, Error2
Please help.
Thanks

select
x.c.value('.', 'nvarchar(128)') as value
from (select cast(xmlString as xml) as data from temp) as t
outer apply t.data.nodes('/response/error') as x(c)
SQL FIDDLE EXAMPLE

correct answer
select STUFF((select ',' + x.c.value('.', 'nvarchar(max)')
from (select cast(xmlString as xml) as data from #temp)
as t outer apply t.data.nodes('/response/error')
as x(c)for xml path('')), 1, 1, '') as Errors

Related

Split values into separate rows

WITH Numbers AS (SELECT Table.ProductNumber FROM Table WITH (NOLOCK))
returns ProductNumber like 1, 2, 3,4,5 - some are comma separated, so I want to split and than do proper SELECT on them with WHERE
What I got so far is:
SELECT #XML = CONVERT(xml,'<root><s>' + REPLACE(Numbers , ',' ,'</s><s>') + '</s></root>')
SELECT [ProductNumber ] = T.c.value('.','varchar(60)') FROM #XML.nodes('/root/s') T(c)
But I dont know how to convert selected SQL resource Numbers into string for XML conversion and not loose track of which ProductNumber were in which row
The problem in your query is you are assigning the converted xml to a variable, but here only the last row will be stored in that variable.
Try something like this.
SELECT Split.a.value('.', 'VARCHAR(100)') splt_num
FROM (SELECT Cast ('<M>'
+ Replace(ProductNumber, ',', '</M><M>')
+ '</M>' AS XML) AS Data
FROM yourtable) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)

how to execute subquery without declaring XML?

why this query is not executing ??
SELECT [Value] = T.c.value('.','varchar(30)') FROM (SELECT '<s>'+ REPLACE ((select tag_id+',' from tbl_container_track for xml path('')),',','</s> <s>')+ '</s>').nodes('/s') T(c)
But this one is working ?
declare #X xml
SELECT #X = (SELECT '<s>'+ REPLACE ((select tag_id+',' from tbl_container_track for xml path('')),',','</s> <s>')+ '</s>')
SELECT [Value] = T.c.value('.','varchar(30)') FROM #X.nodes('/s') T(c)
Can some one help me to simplify without declaring #X ?
Try this: CAST TO XML Datatype you missed
SELECT [Value] = T.c.value('.', 'varchar(30)')
FROM (SELECT Cast(( '<s>' + Replace ((SELECT tag_id+',' FROM tbl_container_track FOR xml path('')), ',', '</s> <s>')
+ '</s>' ) AS XML)) AS Data
CROSS APPLY Data.nodes('/s') T(c)

Query XML field in SQL Server

I am using sql server 2008 R2. I have table X with Column XXML with the following structure
<rec>
<set>
<Raw CLOrderID="GGM-30-08/24/10" Rej="Preopen" Sym="A" Tm="06:36:29.524" />
</set>
</rec>
I want to parse above column XXML and return output as below:
CLOrderID Rej Sym Tm
GGM-30-08/24/10 Preopen A 06:36:29.524
Use nodes() to shred the XML and value() to extract the attribute values.
select T.X.value('#CLOrderID', 'nvarchar(100)') as CLOrderID,
T.X.value('#Rej', 'nvarchar(100)') as Rej,
T.X.value('#Sym', 'nvarchar(100)') as Sym,
T.X.value('#Tm', 'time(3)') as Tm
from dbo.X
cross apply X.XXML.nodes('/rec/set/Raw') as T(X)
If you know for sure that you only will have one row extracted for each XML you can get the attribute values directly without shredding first.
select X.XXML.value('(/rec/set/Raw/#CLOrderID)[1]', 'nvarchar(100)') as CLOrderID,
X.XXML.value('(/rec/set/Raw/#Rej)[1]', 'nvarchar(100)') as Rej,
X.XXML.value('(/rec/set/Raw/#Sym)[1]', 'nvarchar(100)') as Sym,
X.XXML.value('(/rec/set/Raw/#Tm)[1]', 'time(3)') as Tm
from dbo.X
This can be done with a few for xml calls. This structure also remains flexible for future schema changes, provided /rec/set/Raw/#* is present. If that changes, you can always add a pipe with the new path for the attributes you're wanting to grab. Hope this helps.
declare #x table (id int identity(1,1) primary key, x xml)
insert into #x (x) values ('<rec>
<set>
<Raw CLOrderID="GGM-30-08/24/10" Rej="Preopen" Sym="A" Tm="06:36:29.524" />
</set>
</rec>')
select a.id, cast((
select (
select x.attribs.value('local-name(.)','nvarchar(20)') + ' '
from #x t
outer apply t.x.nodes('/rec/set/Raw/#*') x(attribs)
where t.id = a.id
for xml path('')
), (
select x.attribs.value('.','nvarchar(20)') + ' '
from #x t
outer apply t.x.nodes('/rec/set/Raw/#*') x(attribs)
where t.id = a.id
for xml path('')
)
for xml path('')
) as varchar(500))
from #x a

Merge data many rows of one column into a single row in sql server [duplicate]

This question already has answers here:
How to make a query with group_concat in sql server [duplicate]
(4 answers)
Closed 8 years ago.
I have a table like
create table temp_table (col1 int)
I have some data in this table like
insert into temp_table
values(1), (2), (3), (4)
Now I want the data to be output as follows:
1,2,3,4
I have used the query:
select cast(col1 as nvarchar)+','
from temp_table
for xml path('')
The problem is that the output comes in XML format and i need it in simple text/string format. I tried searching for transpose but FOR XML() was mentioned everywhere and it didn't helped me.
Any suggestions?
declare #temp nvarchar(max)
select #temp = COALESCE(#temp + ', ', '') + CAST(col1 as nvarchar) from temp_table
select #temp
And if you really don't get it with the given link :
select STUFF((
SELECT ',' + cast(col1 as nvarchar)
FROM temp_table
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Try this Query
Select STUFF((SELECT ',' + Cast(col1 As nvarchar) FROM temp_table
FOR XML PATH('')), 1, 1, '') As MyColumn

Convert a row as column and merge two column as its value

I have stuck in a select statement, converting rows into columns. I have tried with PIVOT, i was able to convert the single column. But my requirement is little different. I have explained the requirement below.
I have a table structure as below,
I want to select the data as below,
The values in the table are dynamic, which is not a problem for me to deal with that. But i need a way to get the below result.
Could someone please give me a hint on doing it, may be a way to modify the PIVOT below.
select *
from
(
select TSID,AID,Count,BID
from tbl TS
WHERE TS.TPID = 1
) src
pivot
(
sum(Count)
for AID in (AID1,AID2,AID3)
) piv
Thank you..
You may check this fiddle
EDIT
This will work for not previously known column names
DECLARE #Columns AS VARCHAR(MAX)
DECLARE #SQL AS VARCHAR(MAX)
SELECT #Columns = STUFF(( SELECT DISTINCT ',' + AID
FROM Table1
FOR
XML PATH('')
), 1, 1, '')
SET #SQL = '
;WITH MyCTE AS
(
SELECT TSID,
AID,
STUFF(( SELECT '','' + CONVERT(VARCHAR,[Count] )
FROM Table1 I Where I.TSID = O.TSID
FOR
XML PATH('''')
), 1, 1, '''') AS CountList
FROM Table1 O
GROUP BY TSID,
AID
)
SELECT *
FROM MyCTE
PIVOT
(
MAX(CountList)
FOR AID IN
(
' + #Columns + '
)
) AS PivotTable'
EXEC(#SQL)