Inserting 2 delimited strings into SQL Server - sql

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.

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)

Costful XML sql operation

This query works, but it's cost is very big, how to get same result but with less cost?
SELECT ProductID, Split.a.value('.', 'NVARCHAR(60)') ProductNumber FROM (
SELECT ProductID, Cast ('<M>' + Replace(ProductNumber, ',', '</M><M>') + '</M>' AS XML) AS Data FROM Table
) AS A CROSS APPLY Data.nodes ('/M') AS Split(a)

Check the column contains string or not in sql

I have comma-separated string like 675,899,343,294,988.
My table has values like,
ID Values
1 56,78,485
2 90,343,398
3 756,46774,45,4
4 536,394,988
Here i want result like : ID 2,values 343 and ID 4,values 988
Here you can split values to each row for each Id.
;WITH CTE AS
(
-- Convert CSV to rows
SELECT ID,LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'VALUES'
FROM
(
-- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
SELECT ID,CAST ('<M>' + REPLACE([Values], ',', '</M><M>') + '</M>' AS XML) AS Data
FROM YourTable
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
SELECT *
FROM CTE
WHERE (ID=2 AND [VALUES]='343') OR (ID=4 AND [VALUES]='988')
EDIT :
If you want to get matching Id, you can do the below
SAMPLE TABLE
SELECT * INTO #TEMP
FROM
(
SELECT 1 ID, '56,78,485' [Values]
UNION ALL
SELECT 2, '90,343,398'
UNION ALL
SELECT 3, '756,46774,45,4'
UNION ALL
SELECT 4, '536,394,988'
)TAB
QUERY
DECLARE #STR VARCHAR(100)='675,899,343,294,988'
;WITH CTE1 AS
(
SELECT LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'String'
FROM
(
-- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
SELECT CAST ('<M>' + REPLACE(#STR, ',', '</M><M>') + '</M>' AS XML) AS Data
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
,CTE2 AS
(
-- Convert CSV to rows
SELECT ID,LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Values'
FROM
(
-- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
SELECT ID,CAST ('<M>' + REPLACE([Values], ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #TEMP
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
SELECT C2.*
FROM CTE1 c1
JOIN CTE2 C2 ON C1.String=C2.[VALUES]
You can use
SELECT `id` FROM `table` WHERE `Values` IN(string)

Correlation name'Split' is specified multiple times in a FROM clause

I am trying to break comma seperated columns in to rows
here is my last asked question
I got solution for what i asked but suppose if i want to do this same on multiple columns
Here is what i was trying
SELECT OperationTypeId ,[User],[Action],
Split.a.value('.', 'VARCHAR(100)') AS ChangedColumns,
Split.b.value('.', 'VARCHAR(100)') AS OldValue,
Split.c.value('.', 'VARCHAR(100)') AS NewValue
FROM (
SELECT CAST ('<x>' + REPLACE(NewValue, ',', '</x><x>') + '</x>' AS XML) AS NewValue ,
CAST ('<x>' + REPLACE(OldValue, ',', '</x><x>') + '</x>' AS XML) AS OldValue,
OperationTypeId ,[User],[Action] ,CAST ('<x>' + REPLACE(ChangedColumns, ',', '</x><x>') + '</x>' AS XML) AS ChangedColumns
FROM AllRows)AS A
Outer APPLY ChangedColumns.nodes ('/x') AS Split(a)
Outer APPLY OldValue.nodes ('/x') AS Split(b)
Outer APPLY NewValue.nodes ('/x') AS Split(c)
it Gives error
The correlation name 'Split' is specified multiple times in a FROM clause.
Change your query like this. You cannot have same correlation name to convert different columns to rows
SELECT OperationTypeId,
[User],
[Action],
Split.a.value('.', 'VARCHAR(100)') AS ChangedColumns,
Split1.b.value('.', 'VARCHAR(100)') AS OldValue,
Split2.c.value('.', 'VARCHAR(100)') AS NewValue
FROM (SELECT Cast ('<x>' + Replace(NewValue, ',', '</x><x>')
+ '</x>' AS XML) AS NewValue,
Cast ('<x>' + Replace(OldValue, ',', '</x><x>')
+ '</x>' AS XML) AS OldValue,
OperationTypeId,
[User],
[Action],
Cast ('<x>'
+ Replace(ChangedColumns, ',', '</x><x>')
+ '</x>' AS XML) AS ChangedColumns
FROM AllRows)AS A
OUTER APPLY ChangedColumns.nodes ('/x') AS Split(a)
OUTER APPLY OldValue.nodes ('/x') AS Split1(b)
OUTER APPLY NewValue.nodes ('/x') AS Split2(c)

Group by Clause on a query SQL

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