August 18, 2022 at 5:40 pm
Hello,
I am interested in turning one column into multiple rows depending on the value. I tried a pivot but seem to be doing something wrong. Here is some sample code with desired results following:
-- DROP TABLE #t
CREATE TABLE #t (ID int IDENTITY(1,1), CoID int, CoName varchar(100), Class varchar(100))
INSERT INTO #t (CoID, Coname, Class) VALUES (101, 'Apple', 'aaa')
INSERT INTO #t (CoID, Coname, Class) VALUES (101, 'Apple', 'zzz')
INSERT INTO #t (CoID, Coname, Class) VALUES (102, 'Netflix', 'aaa')
INSERT INTO #t (CoID, Coname, Class) VALUES (103, 'Google', 'aaa')
INSERT INTO #t (CoID, Coname, Class) VALUES (104, 'Amazon', 'zzz')
INSERT INTO #t (CoID, Coname, Class) VALUES (105, 'Microsoft', 'zzz')
INSERT INTO #t (CoID, Coname, Class) VALUES (106, 'AMC', 'zzz')
INSERT INTO #t (CoID, Coname, Class) VALUES (107, 'Carnival', 'abc')
INSERT INTO #t (CoID, Coname, Class) VALUES (107, 'Carnival', 'zzz')
INSERT INTO #t (CoID, Coname, Class) VALUES (108, 'BTC', 'abc')
INSERT INTO #t (CoID, Coname, Class) VALUES (109, 'XRP', 'abc')
-- SELECT * FROM #t
Desired output:
Thank you in advance!
August 18, 2022 at 5:49 pm
This SQL will achieve the required results
SELECT Company = src.CoName
, aaa = CASE WHEN src.Class = 'aaa' THEN 'Yes' ELSE '' END
, zzz = CASE WHEN src.Class = 'zzz' THEN 'Yes' ELSE '' END
, abc = CASE WHEN src.Class = 'abc' THEN 'Yes' ELSE '' END
FROM #t AS src
August 18, 2022 at 5:58 pm
Many thanks for the quick reply!
The trouble with the case solution is that I still get mutliple rows per company. What I am hoping to do is consolidate each company to one row and show their classes.
August 18, 2022 at 6:13 pm
Your sample data did not contain any duplicate companies.
To cater for duplicates, wrap each CASE ... END statement in a MAX(CASE ... END)
and add a GROUP BY src.CoName
August 18, 2022 at 7:07 pm
SELECT
CoName,
MAX(CASE WHEN Class = 'aaa' THEN 'Yes' ELSE '' END) AS aaa,
MAX(CASE WHEN Class = 'zzz' THEN 'Yes' ELSE '' END) AS zzz,
MAX(CASE WHEN Class = 'abc' THEN 'Yes' ELSE '' END) AS abc
FROM #t
GROUP BY CoName
ORDER BY CoName
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
August 22, 2022 at 3:44 pm
I attempted some dynamic code with the thought that Class might be more than the 3 values in sample data. To get an empty string instead of a null, I used a second list of the Class column variables with ISNULL as seen in an example by LutzM
There might be better ways to do it, but this was an interesting memory recall with help from previous SLQ Server Central questions.
DECLARE @cols AS NVARCHAR(MAX),
@cols_null_handler AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(Class)
from #t
group by Class
order by Class
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @cols_null_handler = STUFF((SELECT ',ISNULL(' + QUOTENAME(Class) + ','''') AS '+ QUOTENAME(Class)
from #t
group by Class
order by Class
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT CoID, CoName, ' + @cols_null_handler + N' from
(
select CoID, CoName, Class, value=''Yes''
from #t
) x
pivot
(
max(x.value)
for Class in (' + @cols + N')
) p
order by CoID'
exec sp_executesql @query;
August 22, 2022 at 5:03 pm
Have a look at the following article to support such "Dynamic CrossTabs". Use MAX() instead of SUM() like Scott Pletcher did. With the understanding that I have little love for the PIVOT operator, the Dynamic PIVOT code that jschmidt 17654 posted also looks like it'll work.
https://www.sqlservercentral.com/articles/cross-tabs-and-pivots-part-2-dynamic-cross-tabs
--Jeff Moden
Change is inevitable... Change for the better is not.
August 26, 2022 at 8:02 pm
I just noticed that the companies are ordered in the "desired results" by the CoID. To make that happen, here's the code, including the supplied table creation and data insert script:
CREATE TABLE #t (
ID int IDENTITY(1,1),
CoID int,
CoName varchar(100),
Class varchar(100)
);
INSERT INTO #t (CoID, Coname, Class) VALUES (101, 'Apple', 'aaa');
INSERT INTO #t (CoID, Coname, Class) VALUES (101, 'Apple', 'zzz');
INSERT INTO #t (CoID, Coname, Class) VALUES (102, 'Netflix', 'aaa');
INSERT INTO #t (CoID, Coname, Class) VALUES (103, 'Google', 'aaa');
INSERT INTO #t (CoID, Coname, Class) VALUES (104, 'Amazon', 'zzz');
INSERT INTO #t (CoID, Coname, Class) VALUES (105, 'Microsoft', 'zzz');
INSERT INTO #t (CoID, Coname, Class) VALUES (106, 'AMC', 'zzz');
INSERT INTO #t (CoID, Coname, Class) VALUES (107, 'Carnival', 'abc');
INSERT INTO #t (CoID, Coname, Class) VALUES (107, 'Carnival', 'zzz');
INSERT INTO #t (CoID, Coname, Class) VALUES (108, 'BTC', 'abc');
INSERT INTO #t (CoID, Coname, Class) VALUES (109, 'XRP', 'abc');
WITH GROUPED_DATA AS (
SELECT
T.CoName,
MAX(CASE T.Class WHEN 'aaa' THEN 'Yes' ELSE '' END) AS aaa,
MAX(CASE T.Class WHEN 'zzz' THEN 'Yes' ELSE '' END) AS zzz,
MAX(CASE T.Class WHEN 'abc' THEN 'Yes' ELSE '' END) AS abc
FROM #t AS T
GROUP BY T.CoName
)
SELECT
GD.CoName,
GD.aaa,
GD.zzz,
GD.abc
FROM GROUPED_DATA AS GD
CROSS APPLY (
SELECT DISTINCT T1.CoName, T1.CoID
FROM #t AS T1
WHERE T1.CoName = GD.CoName
) AS T
ORDER BY T.CoId;
DROP TABLE IF EXISTS #t;
The results:
CoName aaa zzz abc
---------- ---- ---- ----
Apple Yes Yes
Netflix Yes
Google Yes
Amazon Yes
Microsoft Yes
AMC Yes
Carnival Yes Yes
BTC Yes
XRP Yes
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply