How can I group table after inner join? - sql-server

I am using SQL Server 2012.
I have this table called InspectionReviews:
|Id | SiteId| IsNormal| DateReview | ObjectId |FrequencyId|InspectItemId |
|3379| 5| True | 2016-09-08 00:00:00.000| 1019 | 1 | 16 |
|3380| 5| True | 2016-09-08 00:00:00.000| 1019 | 1 | 20 |
|3381| 5| False | 2016-09-08 00:00:00.000| 1020 | 1 | 16 |
|3382| 5| True | 2016-09-08 00:00:00.000| 1020 | 1 | 54 |
IsNormal is a bit column.
And this table called DamageEvents:
| Id | ExternalId | Subject | CMT |
| 1 | 3379 | damage5 | some comment7 |
| 2 | 3380 | damage3 | some comment3 |
| 3 | 3382 | damage4 | some comment5 |
| 4 | 3381 | damage1 | some comment4 |
The ExternalId column in DamageEvents table is a foreign key.
I wrote an inner join between the two tables:
SELECT
InspectionReviews.Id, InspectionReviews.SiteId,
InspectionReviews.IsNormal, InspectionReviews.DateReview,
InspectionReviews.ObjectId, InspectionReviews.FrequencyId,
InspectionReviews.InspectItemId,
DamageEvents.ExternalId, DamageEvents.Subject, DamageEvents.CMT,
FROM
InspectionReviews
INNER JOIN
DamageEvents ON InspectionReviews.Id = DamageEvents.ExternalId
The result I get:
|Id | SiteId| IsNormal| DateReview | ObjectId |FrequencyId|InspectItemId | ExternalId | Subject | CMT |
|3379| 5 | True | 2016-09-08 00:00:00.000| 1019 | 1 | 16 | 3379 | damage5 | some comment7 |
|3380| 5 | True | 2016-09-08 00:00:00.000| 1019 | 1 | 20 | 3380 | damage3 | some comment3 |
|3381| 5 | False | 2016-09-08 00:00:00.000| 1020 | 1 | 16 | 3381 | damage4 | some comment5 |
|3382| 5 | True | 2016-09-08 00:00:00.000| 1020 | 1 | 54 | 3382 | damage1 | some comment4 |
After I implement inner join I need to make group by ObjectId. And here is desired result:
| Id | SiteId| IsNormal| DateReview | ObjectId |FrequencyId|InspectItemId | Subject | CMT |
|3379,3380| 5 | True | 2016-09-08 00:00:00.000| 1019 | 1 | 16,20 | damage5 | some comment7,some comment3 |
|3381,3382| 5 | False | 2016-09-08 00:00:00.000| 1020 | 1 | 16,54 | damage4 | some comment5,some comment4 |
I need to group the table above after (inner join) by ObjectId, if at least one row has IsNormal false in grouped table it have to be False.
How can I implement it?

You can use query like this:
; with cte as (
SELECT InspectionReviews.Id,
InspectionReviews.SiteId,
InspectionReviews.IsNormal,
InspectionReviews.DateReview,
InspectionReviews.ObjectId,
InspectionReviews.FrequencyId,
InspectionReviews.InpectItemId,
DamageEvents.ExternalId,
DamageEvents.Subject,
DamageEvents.CMT
FROM #inspectionreviews InspectionReviews INNER JOIN
#damageevents DamageEvents ON InspectionReviews.Id = DamageEvents.ExternalId
)
select objectid, min(convert(int,IsNormal)) as IsNormal , stuff ((
select ',' + convert(varchar(5),Id) from cte where objectid = t.objectid
for xml path('')
),1,1,'') as Id
, stuff ((
select ',' + convert(varchar(5),inpectitemid) from cte where objectid = t.objectid
for xml path('')
),1,1,'') as InspectItemId
, stuff ((
select ',' + subject from cte where objectid = t.objectid
for xml path('')
),1,1,'') as Subject
, stuff ((
select ',' + CMT from cte where objectid = t.objectid
for xml path('')
),1,1,'') as CMT,
max(frequencyid) as FrequencyId,
max(SiteId) as SiteId
from cte t group by objectid

May this help-
select
ObjectId,
Id = Stuff( (select ',' + convert(varchar(100), Id)
from InspectionReviews
where ObjectId = ir.ObjectId for xml path('')), 1, 1, ''),
IsNormal = Min(convert(int, IsNormal))
from
InspectionReviews ir
group by
ObjectId

Related

Results of join listed in rows vs additional columns?

I have 2 tables, with the same exact fields and fields names. i am trying to inner join them but im having some difficulty determining how i can get my results in my desired format.
I know i can do select a.customer, a.id, a.date, a.line, a.product, b.customer, b.id, b.date, b.line, b.product but instead of having my A data and B data on the same row, id like for them to be on seperate rows.
I have 2 tables, with the same exact fields and fields names, i am trying to inner join them so that unique line becomes a row.
Table A:
|customer| id | Date | line | Product|
|--------|-----|---------|------|--------|
| 445678 | 123 | 1/1/22 | 10 | 88975 |
| 853652 | 456 | 1/10/22 | 5 | 55876 |
| 845689 | 789 | 1/25/22 | 1 | 45587 |
TABLE B:
|customer| id | Date | line | Product|
|--------|-----|---------|------|--------|
| 445678 | 489 | 1/1/22 | 1 | 87574 |
| 853652 | 853 | 1/10/22 | 12 | 45678 |
| 587435 | 157 | 2/12/22 | 3 | 25896 |
DESIRED RESULTS:
|customer| id | Date | line | Product|
|--------|-----|---------|------|--------|
| 445678 | 123 | 1/1/22 | 10 | 88975 |
| 445678 | 489 | 1/1/22 | 1 | 87574 |
| 853652 | 456 | 1/10/22 | 5 | 55876 |
| 853652 | 853 | 1/10/22 | 12 | 45678 |
my query:
select a.customer, a.id, a.date, a.line, a.product
from data1 a
inner join data2 b
on a.date = b.date
and a.customer = b.customer

MS sql server 2014 select dynamic pivot with lag using last known value for the pivoted column

I have not found an answer yet, so this may not be possible.
I am looking for a pivot query that will replace a pivoted NULL row with the last value available for the column that was not NULL. If the First row is Null then rows are NULL until a row has a value.
Updated When CID changes the rows start as new rows. So if the first row of CID 3 is Null, then the value is null.
Here is my pivot query
DECLARE #Columns AS VARCHAR(MAX)
DECLARE #Query VARCHAR(MAX)
DECLARE #TEMP_DB VARCHAR(255)
SET #TEMP_DB = 'Demo_DataSet'
SELECT #Columns =
COALESCE(#Columns + ', ','') + QUOTENAME(AttrName)
FROM
(
SELECT DISTINCT AttrName
FROM Demo_FirstPass_Data_Raw
) AS B
ORDER BY B.AttrName
SET #Query = '
WITH PivotData AS
(
SELECT
DocID
, Customer
, Version
, CID
, AttrName
, AttrText
FROM Demo_FirstPass_Data_Raw
)
SELECT
DocID
, Customer
, Version
, CID
, ' + #Columns + '
INTO Demo_FirstPass_Data_Pivot
FROM PivotData
PIVOT
(
MAX(AttrText)
FOR AttrName
IN (' + #Columns + ')
) AS PivotResult
Where Version = Version
ORDER BY DocID, Version, CID'
DECLARE #SQL_SCRIPT VARCHAR(MAX)
SET #SQL_SCRIPT = REPLACE(#Query, '' + #TEMP_DB + '', #TEMP_DB)
EXECUTE (#SQL_SCRIPT)
My result is
DocID | Customer | Version | CID | Username | Sales_Order | Date | Description
1852 | Acme | 1 | 2 | User1 | NULL | 11/17/2010 | Product
1852 | Acme | 2 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 3 | 2 | NULL | NULL | 12/15/2010 | NULL
1852 | Acme | 4 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 5 | 2 | NULL | S-0001 | 11/17/2010 | NULL
1852 | Acme | 7 | 2 | NULL | S-0001 | NULL | NULL
1852 | Acme | 8 | 2 | NULL | NULL | 1/14/2011 | NULL
1852 | Acme | 9 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 10 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 1 | 3 | User2 | NULL | 10/10/2010 | Product
1852 | Acme | 2 | 3 | NULL | NULL | NULL | NULL
1852 | Acme | 3 | 3 | NULL | NULL | 12/15/2010 | NULL
What I am looking for is
DocID | Customer | Version | CID | Username | Sales_Order | Date | Description
1852 | Acme | 1 | 2 | User1 | NULL | 11/17/2010 | Product
1852 | Acme | 2 | 2 | User1 | NULL | 11/17/2010 | Product
1852 | Acme | 3 | 2 | User1 | NULL | 12/15/2010 | Product
1852 | Acme | 4 | 2 | User1 | NULL | 12/15/2010 | Product
1852 | Acme | 5 | 2 | User1 | S-0001 | 11/17/2010 | Product
1852 | Acme | 7 | 2 | User1 | S-0001 | 11/17/2010 | Product
1852 | Acme | 8 | 2 | User1 | S-0001 | 1/14/2011 | Product
1852 | Acme | 9 | 2 | User1 | S-0001 | 1/14/2011 | Product
1852 | Acme | 10 | 2 | User1 | S-0001 | 1/14/2011 | Product
1852 | Acme | 1 | 3 | User2 | NULL | 10/10/2010 | Product
1852 | Acme | 2 | 3 | User2 | NULL | 10/10/2010 | Product
1852 | Acme | 3 | 3 | User2 | NULL | 12/15/2010 | Product
Any help is appreciated.
For an unknown number of columns and to integrate into a dynamic pivot, one option is to generate the code for a recursive cte and use that to retain the last non null value based on your partitions like so:
declare #Columns as nvarchar(max)
declare #Query nvarchar(max)
declare #temp_db nvarchar(255)
set #temp_db = 'Demo_DataSet'
select #Columns =
coalesce(#Columns + ', ','') + quotename(AttrName)
from
(
select distinct AttrName
from Demo_FirstPass_Data_Raw
) as B
order by B.AttrName
/* generate isnull statements for columns in recursive cte */
declare #isnull nvarchar(max) = stuff((
select distinct ', isnull(t.'+quotename(d.AttrName)+',cte.'+quotename(d.AttrName)+')'
from Demo_FirstPass_Data_Raw d
order by 1
for xml path (''), type).value('(./text())[1]','nvarchar(max)')
,1,2,'')
set #Query = 'with PivotData as (
select Docid, Customer, Version, cid, AttrName, AttrText
from Demo_FirstPass_Data_Raw
)
, t as (
select
Docid, Customer, Version, cid
, ' + #Columns + '
, rn = row_number() over (partition by DocId, Customer, cid order by Version)
from PivotData
pivot(max(AttrText) for AttrName in (' + #Columns + ')) as PivotResult
)
, cte as (
select [Docid], [Customer], [Version], [cid], ' + #Columns + ', rn
from t
where version = 1
union all
select t.[Docid], t.[Customer], t.[Version], t.[cid]
, '+ #isnull + '
'+',t.rn
from t
inner join cte
on t.rn = cte.rn+1
and t.docid = cte.docid
and t.customer = cte.customer
and t.cid = cte.cid
)
select *
from cte
order by docid, customer, cid, version
'
select #query
exec sp_executesql #query
rextester demo: http://rextester.com/OQZOW62536
code generated:
with PivotData as (
select Docid, Customer, Version, cid, AttrName, AttrText
from Demo_FirstPass_Data_Raw
)
, t as (
select
Docid, Customer, Version, cid
, [Date], [Description], [Sales_Order], [Username]
, rn = row_number() over (partition by DocId, Customer, cid order by Version)
from PivotData
pivot(max(AttrText) for AttrName in ([Date], [Description], [Sales_Order], [Username])) as PivotResult
)
, cte as (
select [Docid], [Customer], [Version], [cid], [Date], [Description], [Sales_Order], [Username], rn
from t
where version = 1
union all
select t.[Docid], t.[Customer], t.[Version], t.[cid]
, isnull(t.[Date],cte.[Date]), isnull(t.[Description],cte.[Description]), isnull(t.[Sales_Order],cte.[Sales_Order]), isnull(t.[Username],cte.[Username])
,t.rn
from t
inner join cte
on t.rn = cte.rn+1
and t.docid = cte.docid
and t.customer = cte.customer
and t.cid = cte.cid
)
select *
from cte
order by docid, customer, cid, version
results:
+-------+----------+---------+-----+------------+-------------+-------------+----------+----+
| Docid | Customer | Version | cid | Date | Description | Sales_Order | Username | rn |
+-------+----------+---------+-----+------------+-------------+-------------+----------+----+
| 1852 | Acme | 1 | 2 | 2010-11-17 | Product | NULL | User1 | 1 |
| 1852 | Acme | 2 | 2 | 2010-11-17 | Product | NULL | User1 | 2 |
| 1852 | Acme | 3 | 2 | 2010-12-15 | Product | NULL | User1 | 3 |
| 1852 | Acme | 4 | 2 | 2010-12-15 | Product | NULL | User1 | 4 |
| 1852 | Acme | 5 | 2 | 2010-11-17 | Product | S-0001 | User1 | 5 |
| 1852 | Acme | 7 | 2 | 2010-11-17 | Product | S-0001 | User1 | 6 |
| 1852 | Acme | 8 | 2 | 2011-01-14 | Product | S-0001 | User1 | 7 |
| 1852 | Acme | 9 | 2 | 2011-01-14 | Product | S-0001 | User1 | 8 |
| 1852 | Acme | 10 | 2 | 2011-01-14 | Product | S-0001 | User1 | 9 |
| 1852 | Acme | 1 | 3 | 2010-10-10 | Product | NULL | User2 | 1 |
| 1852 | Acme | 2 | 3 | 2010-10-10 | Product | NULL | User2 | 2 |
| 1852 | Acme | 3 | 3 | 2010-12-15 | Product | NULL | User2 | 3 |
+-------+----------+---------+-----+------------+-------------+-------------+----------+----+

How to rename column before unpivot? SQL Server

Help I want to rename a column before using the unpivot method
My table is like this:
List item
id| value| ENE| FEB| MAR| ABR| MAY
1 | dsads|2000|2334|2344|2344|2344
after unpivot I get something like this
id| value| month| amount
1 | dads| ENE | 2000
2 | sadf| FEB | 2334
but I want something like this
id| value| month| amount
1 | dads| 01 | 2000
2 | sadf| 02 | 2334
This is my query
select
[año], [Empresa], [Region], [Suc], [CC], [Cuenta],
[Subcuenta], [Descripcion], Periodo, Importe
from
(select * from [dbo].['P Cargado$']) S
unpivot
(Importe for Periodo in
([ENE], [FEB], [MAR], [ABR], [MAY], [JUN], [JUL], [AGO], [SEP],[OCT], [NOV], [DIC])
) AS unpvt;
If you use cross apply(values ..) to unpivot, you could do so like this:
select t.id, t.value, x.*
from t
cross apply (values (1,ene),(2,feb),(3,mar),(4,abr),(5,may)) x (Mnth,Amount)
rextester demo: http://rextester.com/SZDP50356
returns:
+----+-------+------+--------+
| id | value | Mnth | Amount |
+----+-------+------+--------+
| 1 | dsads | 1 | 2000 |
| 1 | dsads | 2 | 2334 |
| 1 | dsads | 3 | 2344 |
| 1 | dsads | 4 | 2344 |
| 1 | dsads | 5 | 2344 |
+----+-------+------+--------+

Group By same or similar string sql

1) Suppose i have a table like this:-
| id | color_code | fruit |
|:------|--------------|----------------:|
| 1 | 000001 | apple |
| 2 | 000001 | apple |
| 3 | 000001 | apple |
| 4 | 000002 | lemon |
| 5 | 000002 | lemon |
| 6 | 000003 | grapes |
| 7 | 000003 | grapes |
How can i group by the fruit column according to the color_code column in sql server?
like this i suppose:-
| id | color_code | fruit | group_concat(id) |
|:------|--------------|-----------------|---------------------|
| 1 | 000001 | apple | 1,2,3 |
| 4 | 000002 | lemon | 2,5 |
| 6 | 000003 | grapes | 6,7 |
2) What if i have 3 tables (like shown below) which require join, how can i achieve this?
series_no table:
| id | desc_seriesno |
|:------|----------------:|
| 7040 | AU1011 |
| 7041 | AU1022 |
| 7042 | AU1033 |
| 7043 | AU1044 |
| 7044 | AU1055 |
| 7045 | AU1066 |
brand table:
| id | desc_brand |
|:------|----------------:|
| 1020 | Audi |
| 1021 | Bentley |
| 1022 | Ford |
| 1023 | BMW |
| 1024 | Mazda |
| 1025 | Toyota |
car_info table:
| seriesno_id | brand_id | color |
|:---------------|------------|--------:|
| 7040 | 1020 | white |
| 7040 | 1020 | black |
| 7040 | 1020 | pink |
| 7041 | 1021 | yellow |
| 7041 | 1021 | brown |
| 7042 | 1022 | purple |
| 7042 | 1022 | black |
| 7042 | 1022 | green |
| 7043 | 1023 | blue |
| 7044 | 1024 | red |
| 7045 | 1025 | maroon |
| 7045 | 1025 | white |
this is my current query with sql server 2014:-
SELECT SN.id AS seriesid, B.id AS brandid, B.desc_brand
FROM [db1].[dbo].[series_no] SN
LEFT JOIN [db1].[dbo].[car_info] CI
ON CI.seriesno_id = SN.id
RIGHT JOIN [db1].[dbo].[brand] B
ON B.id = CI.brand_id
GROUP BY SN.id, B.id
ORDER BY SN.id ASC
but unfortunately it gave me an error since i cannot group by similar string this way.
i want it to be like this:-
| seriesid | brandid | desc_brand | count |
|:-----------|------------|---------------|-------|
| 7040 | 1020 | Audi | 3 |
| 7041 | 1021 | Bentley | 2 |
| 7042 | 1022 | Ford | 3 |
| 7043 | 1023 | BMW | 1 |
| 7044 | 1024 | Mazda | 1 |
| 7045 | 1025 | Toyota | 2 |
1 Fruit Color
Assuming the table name is FruitColor, you can get the desired output by the following query -
SELECT MIN(id) AS id
, color_code
, fruit
, group_concat_id = STUFF((SELECT ',' + CAST(id AS VARCHAR)
FROM FruitColor AS fci
WHERE fci.fruit = fc.fruit AND fci.color_code = fc.color_code
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM FruitColor AS fc
GROUP BY color_code, fruit
ORDER BY id;
The MIN() selects the first id of the group.
Since there is no default GROUP_CONCAT function like in MySql in SQL Server, you have to use the STUFF function and FOR XML PATH. To learn more about group concat you can visit this link https://sqlperformance.com/2014/08/t-sql-queries/sql-server-grouped-concatenation
You can customize the WHERE clause to match only by color_code.
2. You can have several options for this -
Option (a): Show counts for series with brands
SELECT seriesno_id AS seriesid, ci.brand_id AS bandid, desc_brand, COUNT(*) AS [count]
FROM db1.dbo.car_info AS ci
LEFT JOIN db1.dbo.brand AS b ON (b.id = ci.brand_id)
GROUP BY seriesno_id, ci.brand_id, desc_brand;
Here you don't need to use the series table if you want to show counts for cars having brand(s).
You may not need to use the RIGHT JOIN on the brand table because if brand table contains a record which
is not in car_info table, then seriesno_id would be null.
Option (b): Show counts for all the series with or without a brand
SELECT sn.id AS seriesid, ci.brand_id AS bandid, desc_brand, COUNT(*) AS [count]
FROM db1.dbo.series_no AS sn
LEFT JOIN db1.dbo.car_info AS ci ON (ci.seriesno_id = sn.id)
LEFT JOIN db1.dbo.brand AS b ON (b.id = ci.brand_id)
GROUP BY sn.id, ci.brand_id, desc_brand;
Option (c): The work around for selecting a column which is not in a GROUP BY
SELECT seriesno_id AS seriesid, ci.brand_id AS bandid, MAX(desc_brand) AS desc_brand, COUNT(*) AS [count]
FROM db1.dbo.car_info AS ci
LEFT JOIN db1.dbo.brand AS b ON (b.id = ci.brand_id)
GROUP BY seriesno_id, ci.brand_id;
Here, if we are certain that each brand contains only one desc_brand, we can use an aggregate on it.
This is bcause applying aggregate only one value returns that value. I used MAX here.
Personally I would go with option (a) as it makes more sense.
Update on GROUP BY exception for desc_brand being NTEXT...
Cast desc_brand to NVARCHAR to avoid the exception.
CAST(desc_brand AS NVARCHAR(200))
Also I highly recommend using VARCHAR / NVARCHAR instead of any TEXT, CHAR etc. because they usually occupy more memory.
SELECT
id = SUBSTRING(group_concat,1,1),
color_code,
fruit,
group_concat
FROM(
SELECT distinct
m.color_code,
m.fruit,
group_concat = STUFF((SELECT ',' + CONVERT(varchar(10),md.id)
FROM [Test_1].[dbo].[Stuff] md
WHERE m.fruit = md.fruit
AND m.color_code = md.color_code
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM [Test_1].[dbo].[Stuff] m)x
use below code ..
SELECT distinct
m.color_code
, m.fruit
, group_concat = STUFF((
SELECT ',' + CONVERT(varchar(10),md.id)
FROM dbo.tablename md
WHERE m.fruit = md.fruit and m.color_code = md.color_code
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM dbo.tablename m
for second :
SELECT SN.id AS seriesid, B.id AS brandid, B.desc_brand ,count(*)
FROM [db1].[dbo].[series_no] SN
LEFT JOIN [db1].[dbo].[car_info] CI
ON CI.seriesno_id = SN.id
RIGHT JOIN [db1].[dbo].[brand] B
ON B.id = CI.brand_id
GROUP BY SN.id, B.id ,B.desc_brand
ORDER BY 4 ASC

How to retrieve the data on a single row?

I have a table with some data, something like this:
+---------+---------+---------+---------+-------------+
| Column1 | Column2 | Column3 | Column4 | Column5 |
+---------+---------+---------+---------+-------------+
| 38073 | 16 | abc | 444 | 4/28/2015 |
| 38076 | 70 | gug | 555 | 4/30/2015 |
| 38098 | 13 | yyy | 111 | 5/12/2015 |
| 38098 | 13 | yyy | 112 | 5/13/2015 |
| 38098 | 13 | yyy | 113 | 5/14/2015 |
| 38098 | 13 | yyy | 114 | 5/15/2015 |
| 38100 | 17 | abc | 115 | 5/13/2015 |
+---------+---------+---------+---------+-------------+
What I want to do is to have the values from Columns 4 and 5 on a single row, something like this :
+---------+----------+-----------+----------+-----------+----------+-----------+----------+-------------+
| Col1 | Col4Val1 | Col5Val1 | Col4Val2 | Col5Val2 | Col4Val3 | Col5Val3 | Col4Val4 | Col5Val4 |
+---------+----------+-----------+----------+-----------+----------+-----------+----------+-------------+
| 38073 | 444 | 4/28/2015 | null | null | null | null | null | null |
| 38076 | 555 | 4/30/2015 | null | null | null | null | null | null |
| 38098 | 111 | 5/12/2015 | 112 | 5/13/2015 | 113 | 5/14/2015 | 114 | 5/15/2015 |
+---------+----------+-----------+----------+-----------+----------+-----------+----------+-------------+
Appreciate the help if possible.
Thank you.
Bogdan
You can use a UNION to unpivot the data with a CTE, then PIVOT the columns. You can achieve this dynamically too, there are hundreds of articles that will show you how to do that:
;WITH CTE AS (
SELECT [Column1], CAST([Column4] AS VARCHAR) AS [ColumnVals], 'Col4Val'+CAST(ROW_NUMBER() OVER(PARTITION BY [Column1] ORDER BY (SELECT 1)) AS VARCHAR) AS [Pivot]
FROM Table1
UNION
SELECT [Column1], [Column5], 'Col5Val'+CAST(ROW_NUMBER() OVER(PARTITION BY [Column1] ORDER BY (SELECT 1)) AS VARCHAR) AS [Pivot]
FROM Table1)
SELECT [Column1], [Col4Val1], [Col5Val1], [Col4Val2], [Col5Val2], [Col4Val3], [Col5Val3], [Col4Val4], [Col5Val4]
FROM CTE
PIVOT (MAX([ColumnVals]) FOR [Pivot] IN ([Col4Val1], [Col5Val1], [Col4Val2], [Col5Val2], [Col4Val3], [Col5Val3], [Col4Val4], [Col5Val4])) PIV
Here's a working fiddle: http://sqlfiddle.com/#!6/e992f/1

Resources