patternsqlModerate
Is it possible to PIVOT on a LIKE statement
Viewed 0 times
pivotpossiblelikestatement
Problem
Is it possible to group by elements (as in
E.g. Instead of having columns for the statuses
What I have so far:
Table Definition
Table Values
The Pivoted Status Table
Output So Far
```
DB Status Test ACC Test APP Test DBA Prod ACC Prod APP Prod DBA Prod Test Migrated Offline Reserved
--------------- ----------- ----------- ----------- -----------
COLUMN LIKE='Value%') in a PIVOT table? I have a table [DBT].[Status] which contains various statuses (of databases, instances, etc.) and don't want to pivot/query all the PROD and TEST values as single values, but group them.E.g. Instead of having columns for the statuses
Prod, Prod ACC, Prod APP, .. etc. I would have only one column containing the values for Name LIKE 'Prod%' and Name LIKE 'Test%'.What I have so far:
Table Definition
CREATE TABLE [DBT].[Status](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Status] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY],
CONSTRAINT [IX_Status] UNIQUE NONCLUSTERED
(
[Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
GOTable Values
INSERT INTO [DBT].[Status]
(
-- ID -- this column value is auto-generated
Name
)
VALUES
('Test ACC'),
('Test APP'),
('Test DBA'),
('Prod ACC'),
('Prod APP'),
('Prod DBA'),
('Prod'),
('Test'),
('Migrated'),
('Offline'),
('Reserved')The Pivoted Status Table
SELECT 'Database Status' AS [DB Status],
[1] AS [Test ACC], [2] AS [Test APP], [3] AS [Test DBA], [4] AS [Prod ACC], [5] AS [Prod APP], [6] AS [Prod DBA], [7] AS [Prod], [8] AS [Test], [9] AS [Migrated], [10] AS [Offline], [11] AS [Reserved]
FROM
(
SELECT ID, Name FROM [DBT].[Status]
) AS Source
PIVOT
(
COUNT(Name) FOR ID IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11])
) AS PivotTableOutput So Far
```
DB Status Test ACC Test APP Test DBA Prod ACC Prod APP Prod DBA Prod Test Migrated Offline Reserved
--------------- ----------- ----------- ----------- -----------
Solution
SUM(CASE
For a limited number of Names you can use a SUM(CASE solution in this way:
PIVOT
If there is an extensive list of Names but only few of them must be rewritten you can maintain the PIVOT solution:
db<>fiddle here
DYNAMIC QUERY
If you feel a bit lazy and don't want to write all column names, you can use a dynamic query:
db<>fiddle here
For a limited number of Names you can use a SUM(CASE solution in this way:
SELECT
'Database status' as [DB Status],
SUM(CASE WHEN Name LIKE 'Test%' THEN 1 ELSE 0 END) As Test,
SUM(CASE WHEN Name LIKE 'Prod%' THEN 1 ELSE 0 END) AS Prod,
SUM(CASE WHEN Name = 'Migrated' THEN 1 ELSE 0 END) AS Migrated,
SUM(CASE WHEN Name = 'Offline' THEN 1 ELSE 0 END) AS Offline,
SUM(CASE WHEN Name = 'Reserved' THEN 1 ELSE 0 END) AS Reserved
FROM
[Status];PIVOT
If there is an extensive list of Names but only few of them must be rewritten you can maintain the PIVOT solution:
SELECT 'Database Status' AS [DB Status],
[Test], [Prod], [Migrated], [Offline], [Reserved]
FROM
(
SELECT
ID,
CASE
WHEN Name LIKE 'Test%' THEN 'Test'
WHEN Name LIKE 'Prod%' THEN 'Prod'
ELSE Name
END AS Name
FROM
[Status]
) AS Source
PIVOT
(
COUNT(ID) FOR Name IN ([Test], [Prod], [Migrated], [Offline], [Reserved])
) AS PivotTable;db<>fiddle here
DYNAMIC QUERY
If you feel a bit lazy and don't want to write all column names, you can use a dynamic query:
DECLARE @cols nvarchar(max);
SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(CASE WHEN Name LIKE 'Test%' THEN 'Test'
WHEN Name LIKE 'Prod%' THEN 'Prod'
ELSE Name END)
FROM [Status]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE @cmd nvarchar(max);
SET @cmd =
'SELECT ''Database Status'' AS [DB Status],' + @cols + ' FROM
(SELECT
ID,
CASE
WHEN Name LIKE ''Test%'' THEN ''Test''
WHEN Name LIKE ''Prod%'' THEN ''Prod''
ELSE Name
END AS Name
FROM
[Status]
) AS Source
PIVOT
(
COUNT(ID) FOR Name IN (' + @cols + ')
) PVT'
EXEC(@cmd);db<>fiddle here
Code Snippets
SELECT
'Database status' as [DB Status],
SUM(CASE WHEN Name LIKE 'Test%' THEN 1 ELSE 0 END) As Test,
SUM(CASE WHEN Name LIKE 'Prod%' THEN 1 ELSE 0 END) AS Prod,
SUM(CASE WHEN Name = 'Migrated' THEN 1 ELSE 0 END) AS Migrated,
SUM(CASE WHEN Name = 'Offline' THEN 1 ELSE 0 END) AS Offline,
SUM(CASE WHEN Name = 'Reserved' THEN 1 ELSE 0 END) AS Reserved
FROM
[Status];SELECT 'Database Status' AS [DB Status],
[Test], [Prod], [Migrated], [Offline], [Reserved]
FROM
(
SELECT
ID,
CASE
WHEN Name LIKE 'Test%' THEN 'Test'
WHEN Name LIKE 'Prod%' THEN 'Prod'
ELSE Name
END AS Name
FROM
[Status]
) AS Source
PIVOT
(
COUNT(ID) FOR Name IN ([Test], [Prod], [Migrated], [Offline], [Reserved])
) AS PivotTable;DECLARE @cols nvarchar(max);
SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(CASE WHEN Name LIKE 'Test%' THEN 'Test'
WHEN Name LIKE 'Prod%' THEN 'Prod'
ELSE Name END)
FROM [Status]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE @cmd nvarchar(max);
SET @cmd =
'SELECT ''Database Status'' AS [DB Status],' + @cols + ' FROM
(SELECT
ID,
CASE
WHEN Name LIKE ''Test%'' THEN ''Test''
WHEN Name LIKE ''Prod%'' THEN ''Prod''
ELSE Name
END AS Name
FROM
[Status]
) AS Source
PIVOT
(
COUNT(ID) FOR Name IN (' + @cols + ')
) PVT'
EXEC(@cmd);Context
StackExchange Database Administrators Q#247411, answer score: 12
Revisions (0)
No revisions yet.