I am trying to yield a string that reads like Cat1/Cat2/Cat3, etc, from a self-referencing table.
Data looks like this:
CategoryTable
CategoryID, [Name], ParentID
1, Root, 0
2, Cat1, 1
3, Cat2, 2
4, Cat3, 3
5, Cat4, 1
6, Cat5, 5
I want to yield:
Root/Cat1/Cat2/Cat3
Root/Cat4/Cat5
How do I do this in sql server?
You can use CTE
SQL Fiddler
WITH cte AS (
SELECT CategoryID,CAST(Name AS VARCHAR(4000)) AS Name
FROM Category
WHERE ParentID = 0
UNION ALL
SELECT c.CategoryID, CAST(e.Name + '/' + c.Name AS VARCHAR(4000))
FROM cte e
INNER JOIN Category c
ON c.ParentID = e.CategoryID
)
SELECT c1.Name
FrOM cte c1
WHERE NOT EXISTS (SELECT 1 FROM cte c2 where c1.name <> c2.name AND c2.name like c1.NAME + '%')
try this :
DECLARE #str VARCHAR(255) --Or whatever length you need
SET #str = ''
SELECT #str = #str + [Name] + '/' FROM CategoryTable
SET #str = SUBSTRING(#str,0,LEN(#str)) -- remove the trailing '/'
PRINT #str
Related
This query works in one server version but not in another.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[EventDetails]
#EventID AS VARCHAR(20)
AS
BEGIN
WITH CTE(CategoryID, FullCategName, OrderString) AS
(
SELECT
CategoryID,
CAST(CategoryName AS VARCHAR(MAX)),
CAST(CAST(CategoryID AS CHAR(5)) AS VARCHAR(MAX)) OrderString
FROM
CategoryTbl
WHERE
ParentCategoryIDf is NULL
UNION ALL
SELECT
p.CategoryID,
CAST(c.FullCategName + ' >> ' + p.CategoryName AS VARCHAR(MAX)),
CAST(c.OrderString + CAST(p.CategoryID AS CHAR(5)) AS VARCHAR(MAX)) OrderString
FROM
CategoryTbl p
JOIN
CTE c ON c.CategoryID = p.ParentCategoryIDf
)
SELECT
(SELECT TOP 1 i.ImageUrl
FROM ImageTbl i
WHERE i.ProductIDf = p.EventID) AS ImageURL, *
FROM
EventTbl p
LEFT JOIN
CTE c on c.CategoryID = p.CategoryIDf
WHERE
p.EventID = #EventID
END
This is probably a collation issue, try this:
WITH CTE(CategoryID, FullCategName, OrderString) AS (
SELECT
CategoryID
, cast(CategoryName as varchar(max)) Collate SQL_Latin1_General_CP1_CI_AS as FullCategName
, cast(cast(CategoryID as char(5)) as varchar(max)) Collate SQL_Latin1_General_CP1_CI_AS as OrderString
FROM CategoryTbl
WHERE ParentCategoryIDf is NULL
UNION ALL
SELECT
p.CategoryID
, cast(c.FullCategName + ' >> ' + p.CategoryName as varchar(max)) Collate SQL_Latin1_General_CP1_CI_AS
, cast(c.OrderString + cast(p.CategoryID as char(5)) as varchar(max)) Collate SQL_Latin1_General_CP1_CI_AS --OrderString
FROM CategoryTbl p
JOIN CTE c
ON c.CategoryID = p.ParentCategoryIDf
)
select
(select top 1 i.ImageUrl
from ImageTbl i
where i.ProductIDf=p.EventID) as ImageURL
, *
from EventTbl p
left join CTE c on c.CategoryID=p.CategoryIDf
where p.EventID=#EventID
end
Reference:
T-SQL CTE Error: Types don't match between the anchor and the recursive part
Actually i have three columns. ID, MedID, Name. With my query i am getting a result look like the below.
ID MedID Name
1 101 TestData1
1 124 TestData2
Query
select
cmd.ID, mm.MedID,mm.Name as Name
from
tbl1 mm
inner join
tbl2 cmd on cmd.medID= mm.MedID
where
cmd.ID= 1
Actually i am expecting a result like the below
ID MedID Name
1 101,124 TestData1,TestData2
So, how can get a result like this, Where i need to do changes in my query?
Any help appreciated. Thanks in advance !!!
Use STUFF and FOR XML PATH like this:
select id,
stuff((
select ',' + cast(MedId as varchar(30))
from t t1
where t1.id = t.id
order by MedID
for xml path('')
), 1, 1, '') MedID,
stuff((
select ',' + Name
from t t1
where t1.id = t.id
order by MedID
for xml path('')
), 1, 1, '') Name
from t
group by id;
Demo
DECLARE #TABLE TABLE (ID int, MedID varchar(10), Name varchar(10))
INSERT INTO #TABLE VALUES
(1, '101' , 'TestData1'),
(1, '124' , 'TestData2')
SELECT t.ID
, STUFF(( SELECT ', ' + MedID
FROM #TABLE
WHERE ID = t.ID
FOR XML PATH(''),TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') AS MedID
, STUFF(( SELECT ', ' + Name
FROM #TABLE
WHERE ID = t.ID
FOR XML PATH(''),TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') AS Name
FROM #TABLE t
GROUP BY t.ID
I have this query
select
',' + CONVERT(VARCHAR,FileID)
from
[RETRY_INPUT_JSON] A
inner join
RETRY_JSON_STATUS B on JsonStatus = StatusID
where
RetryStatus = 'FAILED'
Union
select
',' + CONVERT(VARCHAR,FileID)
from
[RETRY_INPUT_JSON] A
inner join
RETRY_JSON_STATUS B on SendESBStatus = StatusID
where
RetryStatus In ('FAILED', 'Success')
order by
',' + CONVERT(VARCHAR,FileID)
FOR XML PATH('')
This returns this output:
I want to convert it to varchar.
For that I tried :
DECLARE #FILEID AS VARCHAR(MAX)
SET #FILEID =(SELECT STUFF
(
(
select ',' + CONVERT(VARCHAR,FileID) from [RETRY_INPUT_JSON] A inner join RETRY_JSON_STATUS B
on JsonStatus=StatusID
where RetryStatus='FAILED'
Union
select ',' + CONVERT(VARCHAR,FileID) from [RETRY_INPUT_JSON] A inner join RETRY_JSON_STATUS B
on SendESBStatus=StatusID
where RetryStatus In ('FAILED','Success')
ORDER BY ',' + CONVERT(VARCHAR,FileID) FOR XML PATH('')
),
1, 1, ''
) )
print #FILEID
But I get an error :
Msg 1086, Level 15, State 1, Line 18
The FOR XML clause is invalid in views, inline functions, derived tables, and subqueries when they contain a set operator. To work around, wrap the SELECT containing a set operator using derived table syntax and apply FOR XML on top of it.
Check This.
DECLARE #FILEID AS VARCHAR(MAX)
DECLARE #xml_var XML
SET #xml_var = ( select ',' + CONVERT(VARCHAR,A)
from
(
select
CONVERT(VARCHAR,FileID) A
from
[RETRY_INPUT_JSON] A
inner join
RETRY_JSON_STATUS B on JsonStatus = StatusID
where
RetryStatus = 'FAILED'
Union
select
CONVERT(VARCHAR,FileID) A
from
[RETRY_INPUT_JSON] A
inner join
RETRY_JSON_STATUS B on SendESBStatus = StatusID
where
RetryStatus In ('FAILED', 'Success')
)A
order by A
FOR XML PATH('')
)
select #FILEID = CONVERT(VARCHAR(MAX), #xml_var)
SELECT #FILEID
pRINT #FILEID
I'm create sql syntax which create pivot Group By Product based on Category
CREATE TABLE #Product ( Product varchar(10),Category varchar(10),Stock int)
INSERT INTO #Product Values ('Item A','CatA',10)
INSERT INTO #Product Values ('Item A','CatB',5)
INSERT INTO #Product Values ('Item B','CatA',3)
INSERT INTO #Product Values ('Item B','CatB',5)
INSERT INTO #Product Values ('Item B','CatC',7)
INSERT INTO #Product Values ('Item B','CatD',10)
SELECT *
FROM
(
SELECT Product,Category,Stock
FROM #Product A
) src
pivot
(
SUM(Stock)
for Category in ([CatA], [CatB], [CatC],[CatD])
) piv;
DROP TABLE #Product
Result of Query
Product CatA CatB CatC CatD
Item A 10 5 NULL NULL
Item B 3 5 7 10
Result trying to achieve is
Product Cat1 Stock1 Cat2 Stock2 Cat3 Stock3 Cat4 Stock4
Item A CatA 10 CatB 5 CatC 0 CatD 0
Item B CatA 3 CatB 5 CatC 7 CatD 10
Thanks for the help
You need to create all combinations of Product and Category first. Then do a LEFT JOIN on #Product to get the Stock. Finally, use the result to pivot the data.
Since I'm not familiar with the PIVOT command, I used another technique called Dynamic Crosstab
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql =
'SELECT
Product' + CHAR(10);
SELECT #sql = #sql +
STUFF((
SELECT
' ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), t.RN) + ' THEN Category END) AS ' + QUOTENAME('Cat' + CONVERT(VARCHAR(3), t.RN)) + CHAR(10) +
' ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), t.RN) + ' THEN Stock END) AS ' + QUOTENAME('Stock' + CONVERT(VARCHAR(3), t.RN)) + CHAR(10)
FROM (
SELECT DISTINCT
RN = ROW_NUMBER() OVER(PARTITION BY Product ORDER BY(SELECT NULL))
FROM #Product
) t
FOR XML PATH('')
), 1, 1, ' ');
SELECT #sql = #sql +
'FROM(
SELECT
p1.Product,
p1.Category,
Stock = ISNULL(p2.Stock, 0),
RN = ROW_NUMBER() OVER(PARTITION BY p1.Product ORDER BY p1.Category)
FROM (
SELECT
t1.Product, t2.Category
FROM (
SELECT DISTINCT Product FROM #Product
) t1
CROSS JOIN (
SELECT DISTINCT Category FROM #Product
) t2
) p1
LEFT JOIN #Product p2
ON p1.Product = p2.Product
AND p1.Category = p2.Category
)t
GROUP BY Product;';
PRINT #sql;
EXEC sp_executesql #sql;
ONLINE DEMO
I used a query which splits the texts in a column in one table and retrieves the corresponding id's from another table.
Here is the query:
DECLARE #X XML
DECLARE #STR VARCHAR(MAX) = ''
SELECT #STR = #STR + ';' + P_AUTHOR
FROM sub_aminer_paper
WHERE PID = 4
ORDER BY PID
SELECT #STR = substring(#STR,2,len(#STR))
SELECT #X = CONVERT(xml,' <root> <s>' + REPLACE(#STR,';','</s> <s>') + '</s> </root> ')
SELECT aid as [Author_id], name as [Author_Name]
FROM sub_aminer_author s
INNER JOIN
(SELECT
row_number() OVER(ORDER BY (SELECT null)) AS rn,
T.c.value('.','varchar(max)') AS value
FROM
#X.nodes('/root/s') T(c) ) t ON t.value = s.name
ORDER BY rn
If column p_author contains this value i.e.
Sushil Jajodia;Peter A. Ng;Frederick N. Springsteel
Then this query gives following output i.e.
Author_id Author_Name
578328 Sushil Jajodia
865779 Peter A. Ng
669143 Frederick N. Springsteel
Now I want to have Author_id as skipping first author id e.g. I need output like this:
Author_id Author_Name
865779 Peter A. Ng
669143 Frederick N. Springsteel
Then also I have to insert these Author_id's in another table. Please help regarding this query.
Just add WHERE rn>1
DECLARE #X XML
DECLARE #STR VARCHAR(MAX)=''
SELECT #STR = #STR+';'+P_AUTHOR
FROM sub_aminer_paper
WHERE PID = 4
ORDER BY PID
SELECT #STR = substring(#STR,2,len(#STR))
SELECT #X = CONVERT(xml,' <root> <s>' + REPLACE(#STR,';','</s> <s>') + '</s> </root> ')
SELECT aid as [Author_id], name as [Author_Name]
FROM sub_aminer_author s
INNER JOIN (SELECT row_number()
OVER(ORDER BY (SELECT null)) AS rn, T.c.value('.','varchar(max)') AS value
FROM #X.nodes('/root/s') T(c)
) t ON t.value = s.name
WHERE rn>1
ORDER BY rn