I have a table which looks like this <SubCodeReport3> which has a column called Rank. For each row I need to the what is the Rank and based on that value I need to unpivot SubCode columns (SubCode1,SubCode2 & Subcode3 etc) and convert them into rows.
As seen above for a
Rank 2 Subcode1 & SubCode2 have been unpivoted
Rank 1 SubCode1 has been unpivoted
Rank 3 Subcode1, Subcode2 & SubCode3 have been unpivoted.
there will not be case where the Rank is higher than the no. of available SubCode columns. Any Ideas?
Cursor though rows ?
Here is some SQL to create this sample table
USE TESTDB
GO
/****** Object: Table [dbo].[SubCodeReport3] Script Date: 10/6/2015 2:27:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[SubCodeReport3](
[ S-ID] [varchar](50) NULL,
[Rank] [smallint] NULL,
[AGE] [varchar](50) NULL,
[SchoolCode] [varchar](50) NULL,
[SubCode1] [varchar](50) NULL,
[SubCode2] [varchar](50) NULL,
[SubCode3] [varchar](50) NULL,
[SubCode4] [varchar](50) NULL,
[SubCode5] [varchar](50) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'25', 1, N'23', N'KEN-009', N'ENG', N'MAT', N'ZOO', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'26', 1, N'21', N'DLK-009', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'27', 2, N'25', N'DLK-006', N'MAT', N'ENG', N'STAT', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'28', 1, N'21', N'HLI-005', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'30', 3, N'22', N'INN-009', N'ENG', N'MAT', N'ZOO', N'GEO', N'')
Start with a CTE or derived table that does a full unpivot of the table, and adds a partitioned row_number so that for each row in the original table, SubCode1 will be on row_number 1, SubCode2 on row_number 2, etc.
Then select from that CTE where row_number is less than or equal to [Rank].
You need to CROSS JOIN to a table with sequential numbers:
with cte as
(
select 1 as n
union all select 2
union all select 3
union all select 4
union all select 5
)
select Rank, Age, SchoolCode,
case n
when 1 then SubCode1
when 2 then SubCode2
when 3 then SubCode3
when 4 then SubCode4
when 5 then SubCode5
end as SubCode
from SubCodeReport3
join cte
on n <= rank
See Fiddle
Since you know the number of subcodes you can always do this and your question asks how to UNPIVOT:
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1]
from SubCodeReport3 SCR3
where SCR3.[Rank] = 1) R1
unpivot (SubCode FOR Subject IN (SubCode1)) as unpvt1
UNION ALL
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2]
from SubCodeReport3 SCR3
where SCR3.[Rank] = 2) R1
unpivot (SubCode FOR Subject IN (SubCode1, SubCode2)) as unpvt2
UNION ALL
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3]
from SubCodeReport3 SCR3
where SCR3.[Rank] = 3) R1
unpivot (SubCode FOR Subject IN (SubCode1, SubCode2, SubCode3)) as unpvt3
UNION ALL
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4]
from SubCodeReport3 SCR3
where SCR3.[Rank] = 4) R1
unpivot (SubCode FOR Subject IN (SubCode1, SubCode2, SubCode3, SubCode4)) as unpvt4
UNION ALL
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]
from SubCodeReport3 SCR3
where SCR3.[Rank] = 5) R1
unpivot (SubCode FOR Subject IN (SubCode1, SubCode2, SubCode3, SubCode4, SubCode5)) as unpvt5
See fiddle
This is what worked for me.
WITH CodesReportCTE
(
[Number]
,[ S-ID]
,[Rank]
,[AGE]
,[SchoolCode]
,[Code]
)
AS
(
SELECT
ROW_NUMBER() over (PARTITION BY [ S-ID],[SchoolCode] ORDER BY [ S-ID],[SchoolCode]) AS Number
,[ S-ID]
,[Rank]
,[AGE]
,[SchoolCode]
,up.Code [Code]
FROM [dbo].[SubCodeReport3]
UNPIVOT
(
Code
for x in (SubCode1,SubCode2,SubCode3,SubCode4,SubCode5) ) up
WHERE up.Code <> ' '
)
SELECT
--[Number]
--,
[ S-ID]
,[Rank]
,[AGE]
,[SchoolCode]
,[Code]
FROM CodesReportCTE
WHERE Number <= [Rank]
Related
I have a question about SQL Server: how to convert rows to columns with comma-separated data using bulk data?
CREATE TABLE [dbo].[Emp]
(
[eid] [int] NULL,
[name] [varchar](50) NULL,
[sal] [money] NULL,
[doj] [date] NULL,
[deptno] [int] NULL
)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (1, N'a', 100.0000, CAST(N'2010-10-01' AS Date), 10)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (2, N'bb', 200.0000, CAST(N'2010-02-03' AS Date), 20)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (3, N'c', 300.0000, CAST(N'2017-02-03' AS Date), 30)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (4, N'd', 301.0000, CAST(N'2010-03-04' AS Date), 10)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (5, N'teee', 250.0000, CAST(N'2010-06-04' AS Date), 20)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (7, N'tte', 800.0000, CAST(N'2010-08-09' AS Date), 70)
I want output like below :
userlist
1,2,3,4,5,7
I tried this code:
select distinct
stuff((select ',' + cast(u.eid as varchar)
from emp u
where 1 = 1
for xml path('')), 1, 1, '') as userlist
from emp
Suppose if data has 100 thousand entries, then this query is not returning 100 thousand comma-separated
Could you please tell me how to write query to achieve this task in SQL Server?
I think the query is working as expected. But the result is too large to be displayed in management studio.
here's the script to create the needed data:
CREATE TABLE [dbo].[TestXML](
[ID] [int] NOT NULL,
[PID] [int] NULL,
[Code] [int] NULL,
[Col1] [int] NULL,
[Col2] [int] NULL,
[Col3] [decimal](6, 2) NULL,
[Col4] [decimal](6, 2) NULL,
[Col5] [int] NULL,
CONSTRAINT [PK_TestXML] PRIMARY KEY CLUSTERED ([ID] ASC)
)
GO
CREATE TABLE [dbo].[XML_Columns_Reference](
[TableName] nvarchar(10) NULL,
[TableNameXML] nvarchar(10) NULL,
[ColumnName] nvarchar(10) NULL,
[ColumnNameXML] nvarchar(10) NULL,
[ColumnOrder] [int] NULL,
[GroupName] nvarchar(10) NULL,
[GroupOrder] [int] NULL,
[Category] [int] NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[XML_NoUseCols_Ref](
[TableNameXML] nvarchar(10) NULL,
[Code] [int] NULL,
[ColumnName] nvarchar(10) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[TestXML] ([ID], [PID], [Code], [Col1], [Col2], [Col3], [Col4], [Col5]) VALUES (1, 1000, 10, 1, 2, CAST(0.20 AS Decimal(6, 2)), CAST(0.10 AS Decimal(6, 2)), 1)
INSERT [dbo].[TestXML] ([ID], [PID], [Code], [Col1], [Col2], [Col3], [Col4], [Col5]) VALUES (2, 1000, 20, NULL, 1, CAST(1.00 AS Decimal(6, 2)), CAST(1.00 AS Decimal(6, 2)), 1)
INSERT [dbo].[TestXML] ([ID], [PID], [Code], [Col1], [Col2], [Col3], [Col4], [Col5]) VALUES (3, 1000, 30, NULL, NULL, CAST(2.00 AS Decimal(6, 2)), CAST(2.00 AS Decimal(6, 2)), 5)
INSERT [dbo].[XML_Columns_Reference] ([TableName], [TableNameXML], [ColumnName], [ColumnNameXML], [ColumnOrder], [GroupName], [GroupOrder], [Category]) VALUES (N'TestXML', N'T', N'Col1', N'N', 1, N'A', 2, NULL)
INSERT [dbo].[XML_Columns_Reference] ([TableName], [TableNameXML], [ColumnName], [ColumnNameXML], [ColumnOrder], [GroupName], [GroupOrder], [Category]) VALUES (N'TestXML', N'T', N'Col2', N'V', 2, N'A', 2, NULL)
INSERT [dbo].[XML_Columns_Reference] ([TableName], [TableNameXML], [ColumnName], [ColumnNameXML], [ColumnOrder], [GroupName], [GroupOrder], [Category]) VALUES (N'TestXML', N'T', N'Col3', N'N', 1, N'B', 3, NULL)
INSERT [dbo].[XML_Columns_Reference] ([TableName], [TableNameXML], [ColumnName], [ColumnNameXML], [ColumnOrder], [GroupName], [GroupOrder], [Category]) VALUES (N'TestXML', N'T', N'Col4', N'V', 2, N'B', 3, NULL)
INSERT [dbo].[XML_Columns_Reference] ([TableName], [TableNameXML], [ColumnName], [ColumnNameXML], [ColumnOrder], [GroupName], [GroupOrder], [Category]) VALUES (N'TestXML', N'T', N'Col5', N'A', 1, N'C', 1, NULL)
INSERT [dbo].[XML_NoUseCols_Ref] ([TableNameXML], [Code], [ColumnName]) VALUES (N'T', 20, N'Col1')
INSERT [dbo].[XML_NoUseCols_Ref] ([TableNameXML], [Code], [ColumnName]) VALUES (N'T', 30, N'Col1')
INSERT [dbo].[XML_NoUseCols_Ref] ([TableNameXML], [Code], [ColumnName]) VALUES (N'T', 30, N'Col2')
Here's the query I run:
DECLARE #PID int
SET #PID=1000
SELECT
GroupName as [#n],
(SELECT
Code [#n],
(SELECT
ColumnNameXML as [col/#n],
CASE name
WHEN 'Col1' THEN ISNULL(Col1,0)
WHEN 'Col2' THEN ISNULL(Col2,0)
WHEN 'Col3' THEN ISNULL(Col3,0)
WHEN 'Col4' THEN ISNULL(Col4,0)
WHEN 'Col5' THEN ISNULL(Col5,0)
END AS [col/col_value]
FROM sys.columns
CROSS JOIN TestXML ls1
INNER JOIN XML_Columns_Reference r1
ON sys.columns.name=r1.columnname
WHERE object_id = OBJECT_ID('TestXML') and r1.TableNameXML='T'
and ls1.PID=#PID and ls1.ID=ls2.ID and r1.GroupName=r2.GroupName
and r1.ColumnName NOT IN (SELECT [ColumnName]
FROM XML_NoUseCols_Ref
WHERE TableNameXML='T' and [Code]=ls1.Code
GROUP BY ColumnName)
ORDER BY column_id
FOR XML PATH(''),TYPE
)
FROM TestXML ls2
WHERE ls2.PID=#PID
FOR XML PATH('cat'),TYPE
)
FROM sys.columns
CROSS JOIN TestXML ls3
INNER JOIN XML_Columns_Reference r2
ON sys.columns.name=r2.columnname
WHERE object_id = OBJECT_ID('TestXML') and ls3.PID=#PID and r2.TableNameXML='T'
GROUP BY GroupName
ORDER BY MIN(groupOrder)
FOR XML PATH('grp'),TYPE
Result:
What I need is when there is a reference in XML_NoUseCols_Ref for all the rows of a group (you can get group in XML_Columns_Reference) to eliminated the cat row in the XML.
In the example that would be cat n="30" in grp n="A"
Any kind of help would be appreciated.
Thank you.
Instead of repeating the logic in many places I'd suggest to use a CTE (something like an ad-hoc VIEW) to pre-fetch your data. The rest is rather simple nesting with correlated sub-queries and much better to read:
Hope I got your logic correctly...
WITH cte AS
(
SELECT ls1.ID,ls1.PID,ls1.Code
,r1.ColumnNameXML,r1.GroupName,r1.GroupOrder
,CASE name
WHEN 'Col1' THEN ISNULL(Col1,0)
WHEN 'Col2' THEN ISNULL(Col2,0)
WHEN 'Col3' THEN ISNULL(Col3,0)
WHEN 'Col4' THEN ISNULL(Col4,0)
WHEN 'Col5' THEN ISNULL(Col5,0)
END AS ColumnValue
FROM sys.columns
CROSS JOIN TestXML ls1
INNER JOIN XML_Columns_Reference r1
ON sys.columns.name=r1.columnname
WHERE object_id = OBJECT_ID('TestXML') and r1.TableNameXML='T'
and ls1.PID=#PID
and r1.ColumnName NOT IN ( SELECT [ColumnName]
FROM XML_NoUseCols_Ref
WHERE TableNameXML='T' and [Code]=ls1.Code
GROUP BY ColumnName)
)
SELECT GroupName AS [#n]
,(
SELECT Code AS [#n]
,(
SELECT cte3.ColumnNameXML AS [#n]
,cte3.ColumnValue AS [col_value]
FROM cte cte3
WHERE cte3.GroupName=cte1.GroupName AND cte3.Code=cte2.Code
ORDER BY cte3.ColumnNameXML
FOR XML PATH('col'),TYPE
)
FROM cte cte2
WHERE cte1.GroupName=cte2.GroupName
GROUP BY cte2.Code
ORDER BY cte2.Code
FOR XML PATH('cat'),TYPE
)
FROM cte cte1
GROUP BY GroupName,GroupOrder
ORDER BY GroupOrder
FOR XML PATH('grp');
I have number of CR records and DR records against the same id ,
I need to check sum of DR amount matches with the sum of CR amount for the same id if CR matches with DR then display Balanced column as "Y" else "N"
Required Result: Balanced" column value 'Y' if the Credit and Debit amt column matches and 'N' if they mismatch
Note: single query is needed for this:
As shown in above screen grab red highlighted result is required .
Script is given below :
USE [data]
GO
/****** Object: Table [dbo].[BankData] Script Date: 04-05-2018 3.54.46 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[BankData](
[ID] [int] NOT NULL,
[Name] [nchar](10) NULL,
[Amt] [decimal](18, 0) NULL,
[Type] [char](10) NULL,
[TransId] [int] IDENTITY(1,1) NOT NULL,
[CustId] [int] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[Customer] Script Date: 04-05-2018 3.54.46 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customer](
[CustId] [int] NULL,
[Address] [nvarchar](50) NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[BankData] ON
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (1, N'YASH ', CAST(300 AS Decimal(18, 0)), N'DR ', 1, 1)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (1, N'YASH ', CAST(300 AS Decimal(18, 0)), N'CR ', 2, 1)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(120 AS Decimal(18, 0)), N'DR ', 3, 2)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(140 AS Decimal(18, 0)), N'CR ', 4, 2)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (3, N'RAHUL ', CAST(100 AS Decimal(18, 0)), N'CR ', 5, 3)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (3, N'RAHUL ', CAST(100 AS Decimal(18, 0)), N'DR ', 6, 3)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (4, N'DINESH ', CAST(900 AS Decimal(18, 0)), N'CR ', 7, 4)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (4, N'DINESH ', CAST(900 AS Decimal(18, 0)), N'DR ', 8, 4)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(30 AS Decimal(18, 0)), N'DR ', 9, 2)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(130 AS Decimal(18, 0)), N'DR ', 10, 2)
SET IDENTITY_INSERT [dbo].[BankData] OFF
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (1, N'Mumbai')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (2, N'Delhi')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (3, N'Pune')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (4, N'Banglore')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (5, N'Surat')
If 2012+, this is a small matter using the window function sum() over
Example
Select *
,Balanced = IIF(sum(Amt * IIF([Type]='CR',-1,1)) over (Partition By ID) =0,'Y','N')
from [BankData]
Returns
ID Name Amt Type TransId CustId Balanced
1 YASH 300 DR 1 1 Y
1 YASH 300 CR 2 1 Y
2 FALE 120 DR 3 2 N
2 FALE 140 CR 4 2 N
2 FALE 30 DR 9 2 N
2 FALE 130 DR 10 2 N
3 RAHUL 100 CR 5 3 Y
3 RAHUL 100 DR 6 3 Y
4 DINESH 900 CR 7 4 Y
4 DINESH 900 DR 8 4 Y
I use in-query to get the Balanced column. I group by ID then get the sum of Amt. If type is CR then it is negative (-1*Amt) and if DR it is positive. Then I did a query for table bankData and assign it to it's own ID (t1.ID=t.ID). If sum is zero then it is balanced='Y' else it is not ('N').
select [ID], [Name], [Amt], [Type], [TransId], [CustId],
(select case when sum(case when [Type]='DR' then [Amt] else -1*[Amt] end)=0
then 'Y'
else 'N' end
from [dbo].[BankData] as t1
where t1.[ID] = t.[ID]
group by t1.[ID]) as Balanced
from [dbo].[BankData] as t
order by t.[ID], t.[TransId]
I have a table which looks like this:
How would I select from this table such that the multiple subcode columns transform into rows ? Not sure if this is PIVOT problem. Please advise.
Desired Sample output:
Attached is SQL with data insert scripts for your reference.
USE [TEST]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[SubCodeReport](
[ S-ID] [varchar](50) NULL,
[AGE] [varchar](50) NULL,
[SchoolCode] [varchar](50) NULL,
[SubCode] [varchar](50) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[SubCodeReport3] Script Date: 9/8/2015 6:05:30 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[SubCodeReport3](
[ S-ID] [varchar](50) NULL,
[AGE] [varchar](50) NULL,
[SchoolCode] [varchar](50) NULL,
[SubCode1] [varchar](50) NULL,
[SubCode2] [varchar](50) NULL,
[SubCode3] [varchar](50) NULL,
[SubCode4] [varchar](50) NULL,
[SubCode5] [varchar](50) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'25', N'23', N'KEN-009', N'ENG')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'26', N'21', N'DLK-009', N'ENG')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'27', N'25', N'DLK-006', N'MAT')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'27', N'25', N'DLK-006', N'ENG')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'27', N'25', N'DLK-006', N'STAT')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'28', N'21', N'HLI-005', N'ENG')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'29', N'22', N'NUI-002', N'ENG')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'29', N'22', N'NUI-002', N'MAT')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'30', N'22', N'INN-009', N'ENG')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'30', N'22', N'INN-009', N'MAT')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'30', N'22', N'INN-009', N'ZOO')
INSERT [dbo].[SubCodeReport] ([ S-ID], [AGE], [SchoolCode], [SubCode]) VALUES (N'30', N'22', N'INN-009', N'GEO')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'25', N'23', N'KEN-009', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'26', N'21', N'DLK-009', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'27', N'25', N'DLK-006', N'MAT', N'ENG', N'STAT', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'28', N'21', N'HLI-005', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'29', N'22', N'NUI-002', N'ENG', N'MAT', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'30', N'22', N'INN-009', N'ENG', N'MAT', N'ZOO', N'GEO', N'')
You can use unpivot to get the desired result.
Fiddle with sample data from the question
select [ S-ID], age, schoolcode, u.subcode
from subcodereport3
unpivot
(subcode
for x in (subcode1,subcode2,subcode3,subcode4,subcode5) ) u
where u.subcode <> ' '
I am sorry if the answer has been posted already, but I was not able to find the answer even after searching.
I have the following table
CREATE TABLE [dbo].[emp](
[id] [int] NOT NULL,
[name] [varchar](20) NULL,
[mgrid] [int] NULL
) ON [PRIMARY]
With data
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (1, N'a', 0)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (2, N'a1', 1)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (3, N'a11', 2)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (4, N'a12', 2)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (5, N'a13', 2)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (6, N'a2', 1)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (7, N'a3', 1)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (8, N'a31', 7)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (9, N'a32', 7)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (10, N'b', 0)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (11, N'b1', 10)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (12, N'b2', 10)
And I would like the following output
a
a1
a11
a12
a13
a2
a3
a31
a32
b
b1
b2
Is this possible in SQL Server?
SQLFiddle demo
You can use ' ' instead of '+' in the last line to pad a string.
with t as
(
select id,name,mgrid,1 as level,cast(name as varchar(max)) as path
from emp where mgrid=0
union all
select emp.id,emp.name,emp.mgrid, t.level+1 as level,
t.path+cast(emp.name as varchar(max)) as path
from emp
join t on emp.mgrid=t.id
)
select replicate('+', level)+name from t order by path
with CTE as
(
select *
, level = 1
from emp
where mgrid = 0
union all
select emp.id,
name = cast(space((level) * 3) + emp.name as varchar(20)),
emp.mgrid,
level = level + 1
from emp
inner join CTE on CTE.id = emp.mgrid
)
select name
from CTE
order by ltrim(name)
Query:
DECLARE #temp TABLE
(
[id] [int] NOT NULL,
[name] [varchar](20) NULL,
[mgrid] [int] NULL
)
INSERT INTO #temp ([id], [name], [mgrid])
VALUES
(1, N'a', 0), (2, N'a1', 1),
(3, N'a11', 2), (4, N'a12', 2),
(5, N'a13', 2), (6, N'a2', 1),
(7, N'a3', 1), (8, N'a31', 7),
(9, N'a32', 7), (10, N'b', 0),
(11, N'b1', 10), (12, N'b2', 10)
DECLARE #out VARCHAR(MAX) = ''
;WITH cte AS
(
SELECT *, Lvl = 0, nn = CAST(name AS VARCHAR(MAX))
FROM #temp
WHERE mgrid = 0
UNION ALL
SELECT t.*, c.Lvl + 1, nn = CAST(REPLICATE(' ', c.Lvl + 1) + t.name AS VARCHAR(MAX))
FROM #temp t
JOIN cte c ON c.id = t.mgrid
)
SELECT #out = (
SELECT nn + CHAR(13)
FROM cte
ORDER BY LTRIM(nn)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #out
Output:
a
a1
a11
a12
a13
a2
a3
a31
a32
b
b1
b2
You can use CTE (Comnon table expression to achieve this)
check this sample code:
declare #emp table(
[id] [int] NOT NULL,
[name] [varchar](20) NULL,
[mgrid] [int] NULL
)
INSERT #emp ([id], [name], [mgrid]) VALUES (1, N'a', 0)
INSERT #emp ([id], [name], [mgrid]) VALUES (2, N'a1', 1)
INSERT #emp ([id], [name], [mgrid]) VALUES (3, N'a11', 2)
INSERT #emp ([id], [name], [mgrid]) VALUES (4, N'a12', 2)
INSERT #emp ([id], [name], [mgrid]) VALUES (5, N'a13', 2)
INSERT #emp ([id], [name], [mgrid]) VALUES (6, N'a2', 1)
INSERT #emp ([id], [name], [mgrid]) VALUES (7, N'a3', 1)
INSERT #emp ([id], [name], [mgrid]) VALUES (8, N'a31', 7)
INSERT #emp ([id], [name], [mgrid]) VALUES (9, N'a32', 7)
INSERT #emp ([id], [name], [mgrid]) VALUES (10, N'b', 0)
INSERT #emp ([id], [name], [mgrid]) VALUES (11, N'b1', 10)
INSERT #emp ([id], [name], [mgrid]) VALUES (12, N'b2', 10);
with cte (id,name, MGRID) as
(
select id, name,MGRID
from #emp
union all
select c.id, c.name, c.MGRID
from #emp c
inner join cte p
on c.mgrid = P.id
)
SELECT Distinct * FROM CTE
WITH RCTE AS
(
SELECT id, name, mgrid, CAST('' AS NVARCHAR(MAX)) AS blanks , CAST(name AS NVARCHAR(MAX)) AS ordr
FROM dbo.emp WHERE mgrid = 0
UNION ALL
SELECT e.id, e.name, e.mgrid, blanks + ' ' AS blanks, ordr + e.name AS ordr
FROM dbo.emp e
INNER JOIN RCTE r ON e.mgrid = r.id
)
SELECT blanks + name FROM RCTE
ORDER BY ordr