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)
Related
I am trying to convert a single comma-separated row (column) into multiple rows by using this query:
SELECT
Split.a.value('.', 'VARCHAR(max)') AS String
FROM
(SELECT
CAST ('<M>' + REPLACE(cast([csvdata] as Varchar(max)), ',', '</M><M>') + '</M>' AS XML) AS String
FROM
tboutbound
WHERE
id = '30') AS A
CROSS APPLY
String.nodes ('/M') AS Split(a);
But I get an error:
"XML parsing: line 2, character 36, illegal name character"
It is not possible to update table and change the data?
Any suggestion?
Assuming (hoping) that the data does not contain the sequence <![CDATA[ and ]]> you could do this:
SELECT CAST('<M><![CDATA[' + REPLACE([csvdata], ',', ']]></M><M><![CDATA[') + ']]></M>' AS XML)
FROM t
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=0409a8643577a8b88e326689ab6da5a7
I'm trying to split the value from the model_interested column so that from the whole data only model display
SELECT SUBSTRING(model_interested, 20, CHARINDEX('model', model_interested)) AS model_interested
FROM cust
From the image in model_interested column I wish to only display
"model":"A180"
"model":"A200 AMG FL"
I have tried splitting by number of characters but I don't think it's the right way.
You can use the following solution using SUBSTRING and CHARINDEX:
SELECT SUBSTRING(model_interested, CHARINDEX('"model":"', model_interested) + LEN('"model":"'), CHARINDEX('"', model_interested, CHARINDEX('"model":"', model_interested) + LEN('"model":"')) - (CHARINDEX('"model":"', model_interested) + LEN('"model":"')))
FROM table_name
To get the whole property (with property name and value) you can use the following solution:
SELECT SUBSTRING(model_interested, CHARINDEX('"model":"', model_interested), CHARINDEX('"', model_interested, CHARINDEX('"model":"', model_interested) + LEN('"model":"')) - CHARINDEX('"model":"', model_interested) + 1)
FROM table_name
You can also use JSON_VALUE to get the expected value, but you have to change the data to a valid JSON value:
SELECT JSON_VALUE(REPLACE(REPLACE(model_interested, '{[', '[{'), ']}', '}]'), '$[0].model')
FROM table_name
demo on dbfiddle.uk
If using earlier version of SQL server than 2016, then you can write a query as:
;with cte as
(
SELECT
Split.a.value('.', 'VARCHAR(100)') AS model_interested
FROM (
SELECT CAST ('<M>' + REPLACE([model_interested], '.', '</M><M>') + '</M>' AS XML)
as model_interested_xml
FROM #cust
) AS A CROSS APPLY model_interested_xml.nodes ('/M') AS Split(a)
)
select model_interested
from cte
where CHARINDEX('model',model_interested) > 0
demo here: https://rextester.com/CCW41495
I have a simple select statement that can take a string of prodcodes from a table called WCvsNIRTemps and show them in individual rows.
SELECT
Split.a.value('.', 'VARCHAR(100)') AS ProdCodes
FROM (SELECT
CAST ('<M>' + REPLACE([ProdCodes], ',', '</M><M>') + '</M>' AS XML) AS String
FROM WCvsNIRTemps where TemplateName = 'TempName') AS A CROSS APPLY String.nodes ('/M') AS Split(a)
How can I go about showing two columns of data? The delimited string contains the correct order for both of them. So the first listed prodcode ties to the first item listed in the new column prodnam which I'd like to show. Perhaps a pivot table would be a smart idea. Here is my attempt.
SELECT
Split.a.value('.', 'VARCHAR(100)') AS ProdCodes, Split2.b.value('.', 'VARCHAR(100)') AS ProdNams
FROM (SELECT
CAST ('<M>' + REPLACE([ProdCodes], ',', '</M><M>') + '</M>' AS XML) AS String
FROM WCvsNIRTemps where TemplateName = 'TempName') AS A
CROSS APPLY String.nodes ('/M') AS Split(a),
(SELECT
CAST ('<M>' + REPLACE([ProdNams], ',', '</M><M>') + '</M>' AS XML) AS String
FROM WCvsNIRTemps where TemplateName = 'TempName') AS B
CROSS APPLY String.nodes ('/M') AS Split2(b)
WCvsNIRtemps Table:
**TemplateName | ProdCodes | Prodnams**
TempName prodc1,prodc2,prodc3 prodn1,prodn2,prodn3
Desired Query Output:
**Prodcode | Prodnam**
prodc1 prodn1
prodc2 prodn2
prodc3 prodn3
Try below, it will help you :
;WITH CTE AS(
SELECT M.N.value('.[1]','VARCHAR(8000)') AS PRODUCT_CODES, ROW_NUMBER() over(order by M.N.value('.[1]','VARCHAR(8000)') ASC) as Prod_ID,
P.Q.value('.[1]','VARCHAR(8000)') AS PRODUCT_NAMES, ROW_NUMBER() over(order by P.Q.value('.[1]','VARCHAR(8000)') ASC) as ProdName_ID
FROM
(
SELECT CAST('<XMLROOT><ROWDATA>' + REPLACE(PRODCODES,',','</ROWDATA><ROWDATA>') + '</ROWDATA></XMLROOT>' AS XML) AS X,
CAST('<XMLROOT><ROWDATA>' + REPLACE(PRODNAMS,',','</ROWDATA><ROWDATA>') + '</ROWDATA></XMLROOT>' AS XML) AS Y
FROM TEMPTABLE
)T
CROSS APPLY X.nodes('/XMLROOT/ROWDATA')M(N)
CROSS APPLY Y.nodes('/XMLROOT/ROWDATA')P(Q))
SELECT DISTINCT A.PRODUCT_CODES,B.PRODUCT_NAMES FROM CTE A INNER JOIN CTE B
ON A.PROD_ID=B.PRODNAME_ID ORDER BY A.PRODUCT_CODES
It will give below output :
I hope this help. I would like to thanks my friend Bhushan for helping me in this.
Let say I have a data
ID String
-------------------
1 John, Adam
Based on the below query transpose comma seperated data into rows
SELECT A.[ID],
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT [ID],
CAST ('<M>' + REPLACE([string], ',', '</M><M>') + '</M>' AS XML) AS String
FROM TableA) AS A CROSS APPLY String.nodes ('/M') AS Split(a);
Now, I would like to know what is the reason to have '.' and <M> in our query?
PN: Instead of flagging the post please let me know I will delete the post if it should not be post.
If you print out the string within the CAST, you will see that your text string has been turned into an XML string. The '.' in the split command is merely a location in which to start parsing the XML.
If it is sql server 2016 you can use string_split
create table commasep
(
id int identity(1,1)
,string nvarchar(100)
)
insert into commasep (string) values ('John, Adam'), ('test1,test2,test3')
select id, [value] as String from commasep
cross apply string_split(string,',')
I have managed to separate semi colon separated value to multiple rows in sql 2008 what i need now i to have Count(*) statement on it
ID Answers
1 Agent;Department Store
2 Distributor;Wholesaler
using
SELECT ID,
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT ID,
CAST ('<M>' + REPLACE(Question1, '; ', '</M><M>') + '</M>' AS XML) AS String
FROM Registrations) AS A CROSS APPLY String.nodes ('/M') AS Split(a)
I can get
ID String
1 Agent
1 Department Store
2 Distributor
2 Wholesaler
i just need to get the count(*) of Agent,Department store ..
can i do something like
Select Count(*),String from ( ..above query.. ) group by string ?!
Your attempted query is correct it does work
Do this
select count(*) as Count1,String from
(
SELECT ID,
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT ID,
CAST ('<M>' + REPLACE(Answers, ';', '</M><M>') + '</M>' AS XML) AS String
FROM #t) AS A CROSS APPLY String.nodes ('/M') AS Split(a)
)x
group by x.String
OR like this?
select count(*) as Count1 from
(
SELECT ID,
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT ID,
CAST ('<M>' + REPLACE(Answers, ';', '</M><M>') + '</M>' AS XML) AS String
FROM #t) AS A CROSS APPLY String.nodes ('/M') AS Split(a)
)x
SEE DEMO