Group by column and multiple Rows into One Row multiple columns
As I mention in the comments, what you need here is a PIVOT
or Cross tab; I prefer the latter so what I am going to use.
The non-dynamic solution to this would be as follows:
WITH RNs AS(
SELECT WorkOrder,
TestType,
Result,
ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY should be your ID/always ascending column
FROM dbo.Result)
SELECT WorkOrder,
TestType,
MAX(CASE RN WHEN 1 THEN Result END) AS Result1,
MAX(CASE RN WHEN 2 THEN Result END) AS Result2,
MAX(CASE RN WHEN 3 THEN Result END) AS Result3
FROM RNs R
GROUP BY WorkOrder,
TestType;
The problem, however, is that this "locks" you into 3 results, but you suggest there is an indeterminate number of results. Therefore you need a dynamic solution.
The below will work up to 100 results. if you do need more columns than than, then add more CROSS JOIN
s to N
in the CTE Tally
. This results is something like this (which is quite messy).
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10),
@MaxTally int;
SELECT @MaxTally = MAX(C)
FROM (SELECT COUNT(*) AS C
FROM dbo.Result
GROUP BY WorkOrder,
TestType) R;
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (@MaxTally) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2) --100 rows, add more Ns for more rows
SELECT @SQL = N'WITH RNs AS(' + @CRLF +
N' SELECT WorkOrder,' + @CRLF +
N' TestType,' + @CRLF +
N' Result,' + @CRLF +
N' ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY should be your ID/always ascending column' + @CRLF +
N' FROM dbo.Result)' + @CRLF +
N'SELECT WorkOrder,' + @CRLF +
N' TestType,' + @CRLF +
--Using FOR XML PATH due to not knowing SQL Server version
STUFF((SELECT N',' + @CRLF +
CONCAT(N' MAX(CASE RN WHEN ',T.I,N' THEN Result END) AS Result',T.I)
FROM Tally T
ORDER BY T.I ASC
FOR XML PATH(N''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,3,N'') + @CRLF +
N'FROM RNs R' + @CRLF +
N'GROUP BY WorkOrder,' + @CRLF +
N' TestType;';
PRINT @SQL; --Your best friend.
EXEC sys.sp_executesql @SQL;
Convert multiple rows into one row with multiple columns in T-SQL
Bracket []
your column names
Example or dbFiddle
SELECT *
FROM
(
SELECT CompanyName, Price, Project
FROM dbo.MyTable
) src
PIVOT
(
SUM(Price)
FOR Project IN ([Cleaning], [Vaccuming], [Painting], [VendingMachines], [Wallpapers], [Carpeting])
) piv;
Combining rows into one row with multiple columns of data R
As @Duck mentioned you can do this
library(dplyr)
library(tidyr)
df3 %>%
group_by(ID) %>%
pivot_wider(names_from = TIME,
values_from = SH,
names_prefix = "SH_")
#> # A tibble: 3 x 7
#> # Groups: ID [3]
#> ID Sex Race PRE_WEIGHT POST_WEIGHT SH_POST SH_PRE
#> <dbl> <chr> <chr> <dbl> <dbl> <chr> <chr>
#> 1 1 FEMALE White 168 152 Poor Good
#> 2 2 MALE Hispanic 157 143 Very Poor Poor
#> 3 3 FEMALE Black 129 118 Good Satisfactory
Your data
df3 <- readr::read_table("
ID Sex Race TIME SH PRE_WEIGHT POST_WEIGHT
1 FEMALE White POST Poor 168 152
1 FEMALE White PRE Good 168 152
2 MALE Hispanic POST Very Poor 157 143
2 MALE Hispanic PRE Poor 157 143
3 FEMALE Black POST Good 129 118
3 FEMALE Black PRE Satisfactory 129 118")
Combine column from multiple rows into single row
If you have a known or maximum number of campaigns per orderId, consider a simple conditional aggregation in concert with row_number()
Example
Declare @YourTable Table ([orderId] int,[CampaignName] varchar(50),[DiscountAmount] varchar(50)) Insert Into @YourTable Values
(1,'50% Off','$5.20')
,(1,'10% Off','$1.30')
,(1,'5% Off','$0.57')
Select orderId
,Campaign1 = max(case when RN=1 then CampaignName end)
,Campaign2 = max(case when RN=2 then CampaignName end)
,Campaign3 = max(case when RN=3 then CampaignName end)
,Discount1 = max(case when RN=1 then DiscountAmount end)
,Discount2 = max(case when RN=2 then DiscountAmount end)
,Discount3 = max(case when RN=3 then DiscountAmount end)
From (
Select *
,RN = row_number() over(partition by orderId order by (select null))
From @YourTable
) A
Group By OrderID
Returns
orderId Campaign1 Campaign2 Campaign3 Discount1 Discount2 Discount3
1 50% Off 10% Off 5% Off $5.20 $1.30 $0.57
Excel - condense multiple rows into a single row of multiple columns
You can first prepare your table how you want.
then you can use this formula to get the
=TRANSPOSE(FILTER(Data!$F$4:$F$38,(Data!$A$4:$A$38=$A4)*(Data!$C$4:$C$38=B$2),""))
Pivot Numbered List to Multiple Rows of Set Number of Columns
unpivot with values() and calculate the group of 4 and the column name ordinal of 4 by index.
CREATE TABLE #tmpTest (
CreatedAt Date,
[Index] INT,
[Name] VARCHAR(32), Other VARCHAR(20), Another VARCHAR(20)
);
INSERT INTO #tmpTest ([CreatedAt], [Index], [Name], Other, Another)
VALUES('2022-07-20', 1, 'David', 'a', 'b'),
('2022-07-20', 2, 'Haley', 'c', 'd'),
('2022-07-20', 3, 'John', 'e', 'f'),
('2022-07-20', 4, 'Mark', 'g', 'h'),
('2022-07-20', 5, 'Matt', 'i', 'j'),
('2022-07-20', 6, 'Sarah', 'k', 'l'),
('2022-08-13', 1, 'David', 'm', 'n'),
('2022-08-13', 2, 'Haley', 'o', 'p'),
('2022-08-13', 3, 'John', 'q', 'r');
SELECT P.*
FROM (SELECT T.[CreatedAt],U.COL,U.GRP,U.VAL
FROM #tmpTest AS T
CROSS APPLY(VALUES
(CONCAT('Name',1+(T.[index]-1)%4),1+(T.[index]-1)/4,T.Name),
(CONCAT('Other',1+(T.[index]-1)%4),1+(T.[index]-1)/4,T.Other),
(CONCAT('Another',1+(T.[index]-1)%4),1+(T.[index]-1)/4,T.Another)
) AS U(COL,GRP,VAL)) AS D
PIVOT(MAX(VAL) FOR COL IN (Name1,Other1,Another1,Name2,Other2,Another2,Name3,Other3,Another3,Name4,Other4,Another4)) AS P;
Related Topics
How Does Database Indexing Work
SQL Query to Concatenate Column Values from Multiple Rows in Oracle
Left Outer Join Doesn't Return All Rows from My Left Table
Delete All Duplicate Rows Except For One in MySQL
Split Function Equivalent in T-Sql
SQL Server - Best Way to Get Identity of Inserted Row
How to Return Only the Date from a SQL Server Datetime Datatype
Finding Duplicate Values in a SQL Table
How to (Or Can I) Select Distinct on Multiple Columns
How to Use Parameters in Vba in the Different Contexts in Microsoft Access
How to Return Rows That Have the Same Column Values in MySQL
Adding an Identity to an Existing Column
Calculate Age in MySQL (Innodb)
Truncate (Not Round) Decimal Places in SQL Server
How to Create a Temporary Table in an Oracle Database
Select Max Value of Each Group
Are "From Table1 Left Join Table2" and "From Table2 Right Join Table1" Interchangeable