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 <> ' '
Related
Addendum: I don't have a clue as to why this has close votes because "the results are not reproducible." The schema and data script is provided and the script in question is provided. It's all there.
This query fails:
SELECT
P.Profession AS Profession,
CASE
WHEN P.AverageAnnualSalary >= 200000
THEN 'wow'
WHEN P.AverageAnnualSalary >= 100000
AND P.AverageAnnualSalary <= 199999
THEN 'nice'
WHEN P.AverageAnnualSalary >= 0
AND P.AverageAnnualSalary <= 99999
THEN 'ok'
ELSE P.AverageAnnualSalary
END AS Description
FROM
tProfession2 AS P
ORDER BY
Profession ASC
with this error:
Msg 235, Level 16, State 0, Line 1
Cannot convert a char value to money. The char value has incorrect syntax.
This query works:
SELECT Profession AS Profession,
CASE
WHEN P.AverageAnnualSalary >= 200000 THEN 'wow'
WHEN P.AverageAnnualSalary >= 100000 THEN 'nice'
ELSE 'ok'
END AS Description
FROM tProfession2 P
ORDER BY Profession ASC
This is the schema and data:
/****** Object: Table [dbo].[tProfession2] Script Date: 12/14/2021 10:48:41 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tProfession2](
[ProfessionID] [int] IDENTITY(1,1) NOT NULL,
[Profession] [nchar](50) NOT NULL,
[AverageAnnualSalary] [money] NULL,
CONSTRAINT [PK_tProfession2] PRIMARY KEY CLUSTERED
(
[ProfessionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[tProfession2] ON
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (1, N'Doctor ', 200000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (2, N'Attorney ', 350000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (3, N'Software Engineer ', 120000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (4, N'Cybersecurity Consultant ', 110000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (5, N'Network Engineer ', 111000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (6, N'Farmer ', 200000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (7, N'Chef ', 250000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (8, N'Truck Driver ', 99000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (9, N'Wilderness Guide ', 45000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (10, N'HVAC Technician ', 79000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (11, N'Electrician ', 80000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (12, N'TV Personality ', 450000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (13, N'NFL Quarterback ', 2000000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (14, N'Soccer Player ', 4000000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (15, N'Electrical Engineer ', 130000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (16, N'Computer Engineer ', 135000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (17, N'Business Owner ', 4500000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (18, N'Politician ', 20000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (19, N'City Manager ', 90000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (20, N'Landscaper ', 80000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (21, N'Pilot ', 200000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (22, N'Insurance Salesperson ', 230000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (23, N'Interior Designer ', 55000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (24, N'Architect ', 600000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (25, N'IRS Agent ', 99000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (26, N'Accountant ', 120000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (27, N'Tax Preparer ', 60000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (28, N'Spy ', 0.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (29, N'Military Officer ', 45000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (30, N'Veterinarian ', 300000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (31, N'Roofer ', 67000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (32, N'Arborist ', 76000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (33, N'Painter ', 60000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (34, N'Flight Attendant ', 50000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (35, N'Amish Farmer ', 10000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (36, N'Carpet Installer ', 40000.0000)
GO
INSERT [dbo].[tProfession2] ([ProfessionID], [Profession], [AverageAnnualSalary]) VALUES (37, N'Baker ', 900000.0000)
GO
SET IDENTITY_INSERT [dbo].[tProfession2] OFF
GO
SET ANSI_PADDING ON
GO
/****** Object: Index [IX_tProfession] Script Date: 12/14/2021 10:48:42 AM ******/
ALTER TABLE [dbo].[tProfession2] ADD CONSTRAINT [IX_tProfession2] UNIQUE NONCLUSTERED
(
[Profession] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
As far as I can tell, your ELSE shouldn't be there. For the values you have, your ELSE would only be returned if P.AverageAnnualSalary is negative (unlikely, I assume you don't have staff that pay to work for you), NULL (pointless to then return it, might as well omit the ELSE), or between 199999 and 200000 (for example 199999.7) or between 99999 and 100000 (for example 99999.5).
You don't actually need the upper boundaries. For example if the first WHEN isn't true then the value is already implicitly less than 200000. Then you remove the ELSE completely, thus removing the implicit conversion.
CASE WHEN P.AverageAnnualSalary >= 200000 THEN 'wow'
WHEN P.AverageAnnualSalary >= 100000 THEN 'nice'
WHEN P.AverageAnnualSalary >= 0 THEN 'ok'
END
The issue is simple and straight, in the case statement you are returning the charecter values excpet for the else case. so Just cast the else as string and it'll work
SELECT P.Profession AS Profession,
CASE
WHEN P.AverageAnnualSalary >= 200000
THEN 'wow'
WHEN P.AverageAnnualSalary >= 100000
AND P.AverageAnnualSalary <= 199999
THEN 'nice'
WHEN P.AverageAnnualSalary >= 0
AND P.AverageAnnualSalary <= 99999
THEN 'ok'
ELSE CAST(P.AverageAnnualSalary AS VARCHAR(50))
END AS Description
FROM tProfession2 AS P
ORDER BY Profession ASC
The result of a CASE expression is a single specific data type. SQL Server returns the "highest precedence type from the set of types in result_expressions"
Using data type precedence order you get "ok" and "nice" being converted to money
To solve this
ELSE CAST( P.AverageAnnualSalary AS VARCHAR( 30 ))
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.
So I have a bunch of tables
CREATE TABLE [dbo].[Person](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [nvarchar](max) NULL,
[LastName] [nvarchar](max) NULL,
[ManagerId] [int] NULL,
[Active] [nchar](10) NULL
)
CREATE TABLE [dbo].[LOB](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL
)
CREATE TABLE [dbo].[PersonLOB](
[PersonId] [int] NULL,
[LOBId] [int] NULL
)
INSERT [dbo].[LOB] ([Name]) VALUES (N'Banking')
INSERT [dbo].[LOB] ([Name]) VALUES (N'Insurance')
INSERT [dbo].[LOB] ([Name]) VALUES (N'Real Estate')
INSERT [dbo].[LOB] ([Name]) VALUES (N'Retail Brokerage')
INSERT [dbo].[LOB] ([Name]) VALUES (N'Merger & Acquisition')
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Alfredo', N'Mando', NULL, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Alejandro', N'Mendoza', NULL, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Berto', N'Lao', 2, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Benjamin', N'Mindu', 2, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Ben', N'Uy', NULL, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Bernie', N'Sanders', NULL, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Benjamin', N'Santos', 3, 1)
INSERT [dbo].[Person] ([FirstName], [LastName], [ManagerId], [Active]) VALUES ( N'Cathy', N'Zaragosa', 2, 1)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (1, 1)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (2, 1)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (2, 2)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (2, 3)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (3, 2)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (4, 4)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (4, 5)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (5, 3)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (5, 4)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (6, 5)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (7, 1)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (8, 2)
INSERT [dbo].[PersonLOB] ([PersonId], [LOBId]) VALUES (8, 3)
So on the UI side, display a sample data
FirstName LastName LOBs ManagerName Active
Alfredo Mando Banking Y
Alejandro Mendoza Banking, Insurance Y
Berto Lao Insurance Alejando Mendoza Y
.
.
.
So the question is
How do I select resultset given multiple search terms filters for each column in TSQL?
Given Sample search term filter from the UI
FirstName: 'al', 'o'
LastName: 'do'
LOB: 'Banking'
Active: 'Y'
Expected Result:
FirstName LastName LOBs ManagerName Active
Alfredo Mando Banking Y
Alejandro Mendoza Banking, Insurance Y
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 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]