<Data>abc</Data>
<Data>def</Data>
I want to get data from above tag where child tag is under Parent tag So how to read it into one column in sql server as
Column1
abc,def
DECLARE #x XML = '<parent>
<Data>abc</Data>
<Data>def</Data>
</parent>'
SELECT STUFF((
SELECT ',' + d.value('.', 'nvarchar(20)')
FROM #x.nodes('/parent/Data') AS p(d)
FOR XML PATH('')
), 1, 1, '')
I assume the data is contained in a table with column having XML data type.
Lets assume it is inside the table
#Test(column1 XML)
The values could be retrieved as:
Select Column1.Value('(/Parent/Child)[1]','varchar(100)') as FieldName From #Test
" 1 " denotes that a scalar value is to be returned.
For more information :
Pinal Dave Article
Related
I have a table with the following schema in a SQL Azure DB (2019 compat level):
CREATE TABLE dbo.Properties
(
PropertyId int,
PropertyName nvarchar(100),
PropertyValue nvarchar(1000)
)
I'd like to take the data within this table and turn it into JSON using the value within the PropertyName column as the name of the JSON property, and obviously the PropertyValue value as the JSON property value.
EDIT 12/10/2021:
Importantly, the values within the PropertyName column will not be predictable ahead of time.
For example, consider this data in the table (3 rows):
1, "Color", "Blue"
1, "Name", "John"
1, "Cost", 5
The above would be turned into the following JSON:
{"Color":"Blue", "Name":"John", "Cost":5}
I'm obviously able to do this with a STRING_AGG function like the following:
SELECT '{' + STRING_AGG( '"' + p.PropertyName + '": ''' + p.PropertyValue,''',')
WITHIN GROUP (ORDER BY p.PropertyName) + '}' AS MyJson
FROM dbo.Properties p
GROUP BY p.Id
But I was hoping to use one of the build in JSON functions rather than hack together a big string.
FOR JSON AUTO works from the column names, so one method to get your desired result would be to PIVOT the property names into columns. For example:
SELECT Color, [Name], Cost
FROM dbo.Properties
PIVOT ( MAX( PropertyValue ) For PropertyName In ( [Color], [Name], Cost ) ) pvt
FOR JSON AUTO;
My results:
Of course this is only convenient if your JSON attributes / column names are always known and it's a simple example. For more complex examples, you are probably looking at dynamic pivot, or dynamic SQL and your STRING_AGG example isn't so bad.
I have a database with TV Guide data, and in my description field (VARCHAR) sometimes i have a '|' where behind it is the rating. I used to check this in php, before converting it all to XML, but i would like to do this in SQL.
So if i have this string:
This is the description | rating pg-13
Then i want to keep the
This is the description
but if there is no '|' i want the whole string.
I tried using substring, but can't get it to work.
My query now is:
SELECT *, SUBSTRING(`long_description`, 1, POSITION('|' IN `long_description`)) FROM `programs` WHERE station_id = 1
this works only one way - this gives me the string before the '|' but if there is no '|' it gives an empty column.
Based on the use of backticks, you might be using MySQL. If so, substring_index() does exactly what you want:
select substring_index(long_description, '|', 1)
How about this:
SELECT
*,
IF(long_description LIKE '%|%',
SUBSTRING(`long_description`,
1,
POSITION('|' IN `long_description`)),
long_description)
FROM
`programs`
WHERE
station_id = 1
The IF clause basically just checks if you have a | in the field and applies your routine when this is true. Else it will simply return the complete long_description value.
I have a column in table which is stored in format:
{"field1":"val1","field2":"val4"}
{"field1":"val2","field2":"val5"}
{"field1":"val3","field2":"val6"}
I need to remove all field1 with values(e.g "field1":"val1","field1":"val2","field1":"val3" ) and result should be
{"field2":"val4"}
{"field2":"val5"}
{"field2":"val6"}
I am trying to acheive this via replace but stuck as in '"field1":"val1"' string val1 could be any value like null, some integer.
UPDATE emp SET col = REPLACE(col, '"field1":"val1"', '')
I am stuck due to this dynamic value of val1.
I would prefer to use the JSON_REMOVE function (MySQL) :
UPDATE emp
SET emp.col = JSON_REMOVE(emp.col, '$.field1');
You can also add a WHERE clause :
WHERE emp.col LIKE '%val6%';
References: MySQL JSON_REMOVE and MySQL JSON path
A blog post with examples: MySQL for your JSON
And a note about json path in MySQL:
Propery names in path must be double quoted if the property identifier contains interpunction (spaces, special characters, meta characters) bugs.mysql.com
You can do it like this:
SELECT SUBSTRING(Field, 1, INSTR(Field, '"field1"')) + SUBSTRING(Field, INSTR(Field, '"field2"'), LENGTH(Field)) FROM #Temp
I don't know if this works but this is the idea. (Can't test ATM)
Here is the MsSQL equivalent (works, just tested!):
SELECT SUBSTRING(Field, 0, CHARINDEX('"field1"', Field)) + SUBSTRING(Field, CHARINDEX('"field2"', Field), LEN(Field)) FROM #Temp
Let's say we have following table.
UserId | Message
-------|-------------
1 | Hi, have a nice day
2 | Hi, I had a nice day
I need to have all { Hi,-have-a-nice-day-I-had } words separately.
Is there any way to do that ? What if I want to export words from whole database tables ?
Similar results would be also good.
try this:In Sql server 2005 or above
create table yourtable(RowID int, Layout varchar(200))
INSERT yourtable VALUES (1,'hello,world,welcome,to,tsql')
INSERT yourtable VALUES (2,'welcome,to,stackoverflow')
;WITH SplitSting AS
(
SELECT
RowID,LEFT(Layout,CHARINDEX(',',Layout)-1) AS Part
,RIGHT(Layout,LEN(Layout)-CHARINDEX(',',Layout)) AS Remainder
FROM YourTable
WHERE Layout IS NOT NULL AND CHARINDEX(',',Layout)>0
UNION ALL
SELECT
RowID,LEFT(Remainder,CHARINDEX(',',Remainder)-1)
,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(',',Remainder))
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)>0
UNION ALL
SELECT
RowID,Remainder,null
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)=0
)
SELECT part FROM SplitSting ORDER BY RowID
SQLFIDDLE DEMO
Well, ok, here it goes.
In SQL Server you can use this...
SELECT word = d.value('.', 'nvarchar(max)')
FROM
(SELECT xmlWords = CAST(
'<a><i>' + replace([Message], ' ', '</i><i>') + '</i></a>' AS xml)
FROM MyMessageTbl) T(c)
CROSS APPLY c.nodes('/a/i') U(d)
And I hope that for MySQL you can use the same thing, using XML support - ExtractValue() etc.
EDIT: explanation
- replace([Message], ' ', '</i><i>') replaces e.g. 'my word' with 'my</i><i>word'
- then I add the beginning and the end of xml -> '<a><i>my</i><i>word</i></a>', so I have a valid xml... and cast it to xml type to be able to do something with it
- I select from that xml and shred xml nodes '/a/i' it to rows using CROSS APPLY c.nodes('/a/i');
alias rows using U(d), so one 'i' maps to column d (e.g. 'my')
- d.value('.', 'nvarchar(max)') extracts node content and casts it to character type
I have a table called SerialNos with the following columns:
Id, Parent_Id, SerialNo
There are different SerialNo on a Parent_Id
Like:
Id Parent_Id SerialNo
1 16 abc
2 16 def
3 23 hij
4 23 klm
5 23 nop
I just want to retrieve comma separated SerialNos. for particular Parent_Id
e.g. If Parent_Id is passed 16,then O/p should be : 'abc,def'
and if Parent_Id is passed 23,then O/p should be : 'hij,klm,nop'
here is a nice hack:
DECLARE #csv varchar(1000)
SELECT #csv = COALESCE(#csv+',','') + SerialNo
FROM SerialNos
WHERE Parent_Id = 23
SELECT #csv
Depending upon the database server you can use group_concat. For example if you are using mysql group_concat with a separator of "," will give you the result you are after.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
If you are using a different database server check its documentation it is likely that it will have something similar. Please also keep in mind that some databases don't have this function.
Sorry just saw that your post was tagged sql-server2008. If sql server 2008 does not have group_concat or something similar try this link
http://blog.shlomoid.com/2008/11/emulating-mysqls-groupconcat-function.html
Sorry yet another edit, this will help.
http://groupconcat.codeplex.com/
for sql-server 2008 you can use the following query(with your table name):
select distinct STUFF(ISNULL((SELECT ', ' + x.SerialNo
FROM TableA x
WHERE x.Parent_Id= t.Parent_Id
GROUP BY x.SerialNo
FOR XML PATH (''), TYPE).value('.','VARCHAR(max)'), ''), 1, 2, '')
from TableA t
where Parent_Id = 16
Well i could advice my blog post here, but unfortunately its not in English :).
Here is something similar, just without CLR.
There i am aware of at least 4 solutions:
CLR grouping function (well, code is in english)
Can use cursors (not very fast)
Can use something similar to cursors
Can use XML
So one solution (not the fastest, but easy to write):
Create Function fn_MyFunction
(
#Parent_Id int
)
Returns NVarChar(1000)
As
Begin
Declare #txt NVarChar(1000)
SELECT #txt = COALESCE(#txt + ';' + SerialNo, SerialNo)
FROM dbo.Table Where Parent_Id = #Parent_Id
Return #txt
End