I have a table sales:
SalesID. Date. Geography
1. 2020-01. Italy
1. 2020-01. France
1. 2020-01. UK
2. 2020-02. Italy
2. 2002-02. Canada
3. 2002-08. France
I would like to have a result like this:
SalesID. Date. Geography1 Geography2. Geography3
1. 2020-01. Italy. France. Uk
2. 2020-02. Italy. Canada. Null
3. 2020-08. France
I know how to do pivot the column but the number of Geography is unlimited for a sales id. How to do this?
;WITH L AS(
SELECT SalesID, Date, Geography
from
(
SELECT 1 as SalesID, '2020-01' as Date, 'Italy' as Geography
UNION ALL
SELECT 1, '2020-01', 'France'
UNION ALL
SELECT 1, '2020-01', 'UK'
UNION ALL
SELECT 2, '2020-02', 'Italy'
UNION ALL
SELECT 2, '2020-02', 'Canada'
UNION ALL
SELECT 3, '2002-08', 'France'
)S
),
L1 AS(
SELECT SalesID, Date, Geography
from
(
SELECT 1 as SalesID, '2020-01' as Date, 'Italy' as Geography
UNION ALL
SELECT 1, '2020-01', 'France'
UNION ALL
SELECT 1, '2020-01', 'UK'
UNION ALL
SELECT 2, '2020-02', 'Italy'
UNION ALL
SELECT 2, '2020-02', 'Canada'
UNION ALL
SELECT 3, '2002-08', 'France'
)S
)
SELECT
L.SalesID,L.Date,
STUFF((SELECT '; ' + L1.Geography
FROM L1
WHERE L1.SalesID = L.SalesID
AND L1.Date = L.Date
FOR XML PATH('')), 1, 1, '') [Geography]
FROM L
GROUP BY L.SalesID, L.Date
ORDER BY 1
Here the Output of the SQL Query as a screenshot:
CREATE TABLE MyTable(
SalesID INT,
[Date] varchar(20),
Geography VARCHAR(50)
);
INSERT INTO MyTable(SalesID,[Date],Geography)VALUES
(1,'2020-01','Italy'),(1,'2020-01','France'),
(1,'2020-01','UK'),(2,'2020-02','Italy'),(2,'2020-02','Canada'),
(3,'2020-08','France');
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(a.Geography)
FROM MyTable a
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT date, ' + #cols + ' from
(
select
SalesID
,Date
, Geography
from MyTable
) x
pivot
(
max(Geography)
for Geography in (' + #cols + ')
) p '
execute(#query)
date | Canada | France | Italy | UK
:------ | :----- | :----- | :---- | :---
2020-01 | null | France | Italy | UK
2020-02 | Canada | null | Italy | null
2020-08 | null | France | null | null
db<>fiddle here
Related
I have a table
name | age | city
-------------
joe | 42 | berlin
ben | 42 | munich
anna | 22 | hamburg
pia | 50 | berlin
georg | 42 | munich
lisa | 42 | berlin
Now I would like to get all 42 year old in different columns by city
berlin | munich
-------------
joe | ben
lisa | georg
So I would need something like
SELECT (
SELECT name AS berlin WHERE city = "berlin"
UNION
SELECT name AS munich WHERE city = "munich")
FROM TABLE
WHERE
age = 42
Best from Berlin
Joerg
I think you want aggregation:
select max(case when city = 'berlin' then name end) as berlin,
max(case when city = 'munich' then name end) as munich
from (select t.*, row_number() over (partition by city order by name) as seqnum
from t
where city in ('berlin', 'munich') and age = 42
) t
group by seqnum
order by seqnum;
Using PIVOT for example I did it with SQL Server. Hope this can help you.
DECLARE #columns varchar(MAX);
DECLARE #sql nvarchar(max)
CREATE TABLE #Table
(
idPerson int,
firstName varchar(10),
age int,
city varchar(10)
);
INSERT INTO #Table
SELECT '1', 'joe', '42','berlin' UNION ALL
SELECT '2', 'ben', '42','munich' UNION ALL
SELECT '3', 'Ana', '22','hamburg' UNION ALL
SELECT '4', 'pia', '50','berlin' UNION ALL
SELECT '5', 'george', '42','munich' UNION ALL
SELECT '6', 'lisa', '42','munich'
--SELECT * from #Table
SET #columns = STUFF(
(
SELECT
',' + QUOTENAME(LTRIM(city))
FROM
(SELECT DISTINCT city
FROM #Table
) AS T
ORDER BY
city
FOR XML PATH('')
), 1, 1, '');
SET #sql = N'
SELECT
*
FROM
(
SELECT idPerson ,firstName ,age ,city
FROM #Table
--WHERE age = 42
) AS T
PIVOT
(
MAX(firstName)
FOR city IN (' + #columns + N')
) AS P order by age;';
EXEC sp_executesql #sql;
DROP TABLE #Table;
Thanks for your help! Based on the answer of Gordon Linhoff I got this solution:
SELECT max(case when city = 'berlin' then name end) as berlin,
max(case when city = 'munich' then name end) as munich
FROM TABLE
WHERE age = 42
;
I have stored my record data on SQL server and I want to get what should be a simple query to get the total count of each type of my record. I have a table with the following pattern:
Id | Type | ID_Type |
-----------------------
1 | Bags | B1 |
2 | Shoes | S1 |
3 | Shoes | S1 |
4 | Bags | B1 |
..
The Type of my record is dynamic it's working like a category if the user added new Type like Shirts and created new record my query should also get the total of Shirts. Here's my sample data:
Id | Type | ID_Type |
------------------------
1 | Bags | B1 |
2 | Shoes | S1 |
3 | Shoes | S1 |
4 | Bags | B1 |
5 | Shirts | S2 |
6 | Shirts | S2 |
7 | Shirts | S2 |
..
Below is the result I would like to get with total of records:
Bags | Shoes | Shirts | Total |
-------------------------------
2 | 2 | 3 | 7
You can create dynamic PIVOT like following. To generate the Total column you can simply use WITH ROLLUP in GROUP BY
DECLARE #cols AS NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename([Type])
FROM [YourTableName]
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '') + ',[Total]';
EXECUTE('SELECT * FROM (select ISNULL(type, ''total'') as Type,Count(*) n
from [YourTableName] GROUP BY [Type] WITH ROLLUP) s
PIVOT (max(n) FOR [Type] IN ('+#cols+') ) pvt')
Online Demo
Output
+------+--------+-------+-------+
| Bags | Shirts | Shoes | Total |
+------+--------+-------+-------+
| 2 | 3 | 2 | 7 |
+------+--------+-------+-------+
You can do with case statement in this way.
with cte as (
Select 1 as ID, 'Bags' as [Type] union all
Select 2 as ID, 'Shoes' as [Type] union all
Select 3 as ID, 'Shoes' as [Type] union all
Select 4 as ID, 'Bags' as [Type] union all
Select 5 as ID, 'Shirts' as [Type] union all
Select 6 as ID, 'Shirts' as [Type] union all
Select 7 as ID, 'Shirts' as [Type] )
select count(case when [type] ='Bags' then ID end) Bags, count(case when [type]
='Shoes' then ID end) Shoes ,
count(case when [type] ='Shirts' then ID end) Shirts, count(1) total from cte;
Output:
Bags Shoes Shirts total
2 2 3 7
Using Dynamic SQL approach:
IF the columns are dynamic then you can achieve your results in this way.
Test Data:
-- drop table #temp
Select 1 as ID, 'Bags' as [Type] into #temp union all
Select 2 as ID, 'Shoes' as [Type] union all
Select 3 as ID, 'Shoes' as [Type] union all
Select 4 as ID, 'Bags' as [Type] union all
Select 5 as ID, 'Shirts' as [Type] union all
Select 6 as ID, 'Shirts' as [Type] union all
Select 7 as ID, 'Shirts' as [Type]
--drop table #temp1
select *, ROW_NUMBER() over (partition by [Type] order by ID) Rownum
into #temp1 from #temp
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Type)
FROM #temp c
FOR XML PATH(''))
,1,1,'')
set #query = 'SELECT '+#cols+' ,total from
(
select Type, ID, total
from #temp1 t
join (select count(1) total from #temp1) t1 on 1= 1
) x
pivot
(
count(ID)
for Type in (' + #cols + ')
) p '
Exec sp_executesql #query
Output:
Bags Shirts Shoes total
2 3 2 7
I Have three tables like bellow
**tRole**
+--------+----------+-----------+
| RoleID | RoleCode | RoleTitle |
+--------+----------+-----------+
| 1 | Role1 | RT1 |
| 2 | Role2 | RT2 |
| 3 | Role3 | RT3 |
+--------+----------+-----------+
**tEmployee**
+-------+-------+
| EmpID | Name |
+-------+-------+
| 1 | Emp 1 |
| 2 | Emp 2 |
| 3 | Emp 3 |
+-------+-------+
**tEmployeeRole**
+-------+--------+
| EmpID | RoleID |
+-------+--------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 3 | 3 |
+-------+--------+
I want a output like below ,If a role mapped with only one employee then employee name will show other wise Multiple will show.
+--------+----------+-----------+----------+
| RoleID | RoleCode | RoleTitle | Employee |
+--------+----------+-----------+----------+
| 1 | Role1 | RT1 | Multiple |
| 2 | Role2 | RT2 | Multiple |
| 3 | Role3 | RT3 | Emp 3 |
+--------+----------+-----------+----------+
I write bellow query but when I group by emp.First_Name then the result is wrong
select cr.RoleCode,cr.RoleID,
case
when count(ear.RoleID)=1 then emp.First_Name
else 'M' end as 'AssignedTO'
from tRole as cr
left outer join tEmployeeRole as ear on cr.RoleID=ear.RoleID
left outer join tEmployee as emp on ear.EmployeeID=emp.EmployeeID
group by cr.RoleCode,crRoleID,emp.First_Name
Hello You can use this query for your solution :
you need to count with partition and use distinct data
DECLARE #tRole TABLE (
RoleID INT
,RoleCode VARCHAR(50)
,RoleTitle VARCHAR(50)
)
DECLARE #tEmployee TABLE (
EmpID INT
,EmpName VARCHAR(50)
)
DECLARE #tEmployeeRole TABLE ( EmpID INT, RoleID INT )
INSERT #tRole ( RoleID, RoleCode, RoleTitle )
SELECT 1, 'Role1', 'RT1'
UNION
SELECT 2, 'Role2', 'RT2'
UNION
SELECT 3, 'Role3', 'RT3'
INSERT #tEmployee ( EmpID, EmpName )
SELECT 1, 'Epm 1'
UNION
SELECT 2, 'Epm 2'
UNION
SELECT 3, 'Epm 3'
INSERT #tEmployeeRole ( EmpID, RoleID )
SELECT 1, 1
UNION
SELECT 1, 2
UNION
SELECT 2, 1
UNION
SELECT 2, 2
UNION
SELECT 3, 3
SELECT DISTINCT tRole.RoleID
, RoleCode
, RoleTitle
, CASE WHEN COUNT(tEmployeeRole.EmpID) OVER ( PARTITION BY tEmployee.EmpID ) = 1 THEN tEmployee.EmpName ELSE 'Multiple'END [Employee]
FROM #tEmployee tEmployee
LEFT OUTER JOIN #tEmployeeRole tEmployeeRole ON tEmployeeRole.EmpID = tEmployee.EmpID
LEFT OUTER JOIN #tRole tRole ON tRole.RoleID = tEmployeeRole.RoleID
You can Modify the answer from #Pratik to add a col that lists the employees
;with CTE as(
SELECT
DISTINCT tRole.RoleID
RoleCode
, RoleTitle
, CASE WHEN COUNT(tEmployeeRole.EmpID) OVER ( PARTITION BY tEmployee.EmpID ) = 1 THEN tEmployee.EmpName ELSE 'Multiple'END [Employee]
FROM #tEmployee tEmployee
LEFT OUTER JOIN #tEmployeeRole tEmployeeRole ON tEmployeeRole.EmpID = tEmployee.EmpID
LEFT OUTER JOIN #tRole tRole ON tRole.RoleID = tEmployeeRole.RoleID
)
select *
,stuff( (select ','+EmpName from #tEmployee IE inner join #tEmployeeRole IER on IE.EmpID = IER.EmpID where IER.RoleID = CTE.rolecode for xml PATH('') ),1,1,'') AS EMList
from CTE
This query might help you out . Make a try
Your Tables Data looks like
create TABLE #tRole (RoleID INT ,RoleCode VARCHAR(50) ,RoleTitle VARCHAR(50) )
create TABLE #tEmployee (EmpID INT ,EmpName VARCHAR(50) )
create TABLE #tEmployeeRole( EmpID INT, RoleID INT )
INSERT #tRole ( RoleID, RoleCode, RoleTitle )
SELECT 1, 'Role1', 'RT1'
UNION
SELECT 2, 'Role2', 'RT2'
UNION
SELECT 3, 'Role3', 'RT3'
INSERT #tEmployee ( EmpID, EmpName )
SELECT 1, 'Epm 1'
UNION
SELECT 2, 'Epm 2'
UNION
SELECT 3, 'Epm 3'
INSERT #tEmployeeRole ( EmpID, RoleID )
SELECT 1, 1
UNION
SELECT 1, 2
UNION
SELECT 2, 1
UNION
SELECT 2, 2
UNION
SELECT 3, 3
Desired Query
;with cte as
(
select tr.roleid,tr.rolecode,tr.roletitle,te.empname
,COUNT(ter.EmpID) OVER ( PARTITION BY ter.EmpID ) as emp_count
from #tEmployee te
inner join #tEmployeeRole tER on tER.empid=te.empid
inner join #tRole tr on tr.roleid=ter.roleid
)
select distinct RoleID,RoleCode,RoleTitle
,case when emp_count>1 then 'Multiple' else empname end as Employee
from cte
I found this great post for transposing a table in sql:
Simple way to transpose columns and rows in Sql?
edit:
input:
Paul | John | Tim | Eric
Red 'hi' | 5 | 1 | 3.3
Green 'there' | 4 | 3 | 5.5
Blue 'everyone'| 2 | 9 | 7.5
expected output:
Red | Green | Blue
Paul 'hi' | 'there' | 'everyone'
John 5 | 4 | 2
Tim 1 | 3 | 9
Eric 3.3 | 5.5 | 7.5
And I wanted to employ the last dynamic solution for a table that has different data types dynamically:
CREATE TABLE yourTable([color] nvarchar(5), [Paul] nvarchar(10), [John] int, [Tim]
int, [Eric] float);
INSERT INTO yourTable
([color], [Paul], [John], [Tim], [Eric])
VALUES
('Red', 'hi', 5, 1, 3.3),
('Green', 'there', 4, 3, 5.5),
('Blue', 'everyone', 2, 9, 7.5);
When I run the code from the previous answer:
DECLARE #colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsPivot as NVARCHAR(MAX)
select #colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('yourtable') and
C.name <> 'color'
for xml path('')), 1, 1, '')
select #colsPivot = STUFF((SELECT ','
+ quotename(color)
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'select name, '+#colsPivot+'
from
(
select color, name, value
from yourtable
unpivot
(
value for name in ('+#colsUnpivot+')
) unpiv
) src
pivot
(
sum(value)
for color in ('+#colsPivot+')
) piv'
exec(#query)
When I run this code I get the error message:
The type of column "John" conflicts with the type of other columns specified in the UNPIVOT list.
Is there a way that I can use this dynamic solution for my table without losing the dynamic nature of it? I'd like to ideally pass a bunch of tables into this method to transpose them in batch.
Thanks
A method to overcome this would be to use the data type SQL_VARIANT so that the resulting columns can handle more than a single data type. However you cannot SUM() SQL_VARIANT columns, so sum(value) has to be changed to max(value) - or min(value) - but for this pivot that change does not alter the result.
DECLARE #colsConvert AS NVARCHAR(MAX)
DECLARE #colsUnpivot AS NVARCHAR(MAX)
DECLARE #colsPivot as NVARCHAR(MAX)
DECLARE #query AS NVARCHAR(MAX)
select #colsConvert = (select ', cast('+quotename(C.name)+' as sql_variant) as '+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('yourtable') and
C.name <> 'color'
for xml path(''))
select #colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('yourtable') and
C.name <> 'color'
for xml path('')), 1, 1, '')
select #colsPivot = STUFF((SELECT ','
+ quotename(color)
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'select name, '+#colsPivot+'
from
(
select color, name, value
from (select color'+#colsConvert+' from yourtable) as converted
unpivot
(
value for name in ('+#colsUnpivot+')
) unpiv
) src
pivot
(
max(value)
for color in ('+#colsPivot+')
) piv'
exec(#query)
See this working at: http://rextester.com/IBSN39688
Result:
+------+-----+-------+----------+
| name | Red | Green | Blue |
+------+-----+-------+----------+
| Eric | 3.3 | 5.5 | 7.5 |
| John | 5 | 4 | 2 |
| Paul | hi | there | everyone |
| Tim | 1 | 3 | 9 |
+------+-----+-------+----------+
The generated SQL:
select name, [Red],[Green],[Blue]
from
(
select color, name, value
from (select color, cast([Eric] as sql_variant) as [Eric], cast([John] as sql_variant) as [John], cast([Paul] as sql_variant) as [Paul], cast([Tim] as sql_variant) as [Tim] from yourtable) as converted
unpivot
(
value for name in ([Eric],[John],[Paul],[Tim])
) unpiv
) src
pivot
(
max(value)
for color in ([Red],[Green],[Blue])
) piv
+EDIT
An added benefit of using SQL_VARIANT in the result columns is that each standard data type encountered will adopt its default format. Particularly relevant for decimal/float and date/time data. You could also amend the defaults before running the dynamic pivot to further influence the output.
Demonstrated here
The following will transpose virtually any table, view, or query while respecting Row and Column sequences.
Full Disclosure: There is one major drawback. This approach does NOT handle NULL values well. A NULL value will cause the following columns to shift to the left.
Example
Declare #YourTable Table ([Color] varchar(50),[Paul] varchar(50),[John] int,[Tim] int,[Eric] decimal(10,1))
Insert Into #YourTable Values
('Red','hi',5,1,3.3)
,('Green','there',4,3,5.5)
,('Blue','everyone',2,9,7.5)
Declare #XML xml = (Select *,RowNr=Row_Number() over (Order By (Select NULL)) From #YourTable for XML RAW)
Select RowNr = Row_Number() over(Partition By r.value('#RowNr','int') Order By (Select null))
,ColNr = r.value('#RowNr','int')
,Item = attr.value('local-name(.)','varchar(100)')
,Value = attr.value('.','varchar(max)')
Into #Temp
From #XML.nodes('/row') as XN(r)
Cross Apply XN.r.nodes('./#*') AS XA(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('RowNr')
Declare #SQL varchar(max) = '
Select [Item],' + Stuff((Select Distinct ',' + QuoteName(ColNr)+' as '+QuoteName(Value) From #Temp Where RowNr=1 Order by 1 For XML Path('')),1,1,'') + '
From #Temp
Pivot (max([Value]) For [ColNr] in (' + Stuff((Select Distinct ',' + QuoteName(ColNr) From #Temp Order by 1 For XML Path('')),1,1,'') + ') ) p
Where RowNr>1
Order By RowNr'
Exec(#SQL);
Returns
Item Red Green Blue
Paul hi there everyone
John 5 4 2
Tim 1 3 9
Eric 3.3 5.5 7.5
dbFiddle
I'm currently working on a SQL query in T-SQL on SQL Server 2012 with the objective to concate or merge several tables into 1 table and concate several rows. So far it's working out fine. I use STUFF and FOR XML PATH to concate several rows into 1.
Unfortunately, when I want to merge my 2 temporary tables into 1 final result table, the concatinated (merged) rows disappear again.
My tables look the following way:
table #BasicOffers
OfferId | Tile | Manager | DeliveryVersionId |
----------+--------+----------+-------------------|
4 | Offer1 | John Doe | 1 |
5 | Offer2 | Jane Doe | 2 |
table #TmpLabels
DeliveryVersionId | Label |
------------------+-------------------------+
1 | Service, Time, Material |
2 | Consulting, Time |
final result, unfortunately not the desired output. the temporary tables seem to be split-up again:
OfferId | Title | Manager | Delivery
----------+--------+----------+------------------------
4 | Offer1 | John Doe | Service
4 | Offer1 | John Doe | Time
4 | Offer1 | John Doe | Material
5 | Offer2 | Jane Doe | Consulting
5 | Offer2 | Jane Doe | Time
Desired Output:
OfferId | Title | Manager | Delivery
----------+--------+----------+------------------------
4 | Offer1 | John Doe | Service, Time, Material
5 | Offer2 | Jane Doe | Consulting, Time
My query to merge the tables looks like this:
-- Delivery Methods
SELECT [D].DeliveryVersionId, [DM].Label
INTO #TmpLabels
FROM [MySchema].[Delivery] [D]
INNER JOIN dbo.DeliveryMethods [DM] ON [DM].DeliveryMethodId = [D].DeliveryMethodId
SELECT DeliveryVersionId,
Label = STUFF(
(SELECT ',' + Label FROM #TmpLabels FOR XML PATH('')), 1, 1, ''
)
FROM #TmpLabels
GROUP BY DeliveryVersionId
-- FinalResults
SELECT [O].OfferId, [O].Title, [O].OfferManager, [DL].Label AS Delivery
FROM #BasicOffers [O]
INNER JOIN #TmpLabels [DL] ON [DL].DeliveryVersionId = [O].DeliveryVersionId
I don't really know, if it's the best solution to store everything into a temporary table and then merge it or to select it all at once.
In any case unfortunately my query seems not to work correctly.
Do you have an idea on how to solve this issue?
Thanks a lot!
;WITH BasicOffers(OfferId,Tile,Manager,DeliveryVersionId )
AS
(
SELECT 4 , 'Offer1' , 'John Doe' , 1 Union all
SELECT 5 , 'Offer2' , 'Jane Doe' , 2
)
,TmpLabels(DeliveryVersionId,Label)
AS
(
SELECT 1 , 'Service, Time, Material ' Union all
SELECT 2 , 'Consulting, Time'
)
Select B.OfferId,B.Tile,B.Manager, T.Label AS Delivery
From BasicOffers B
INNER JOIN TmpLabels T
ON T.DeliveryVersionId=B.DeliveryVersionId
--To COnvert into Comma separated
;WITH Cte_Convert(OfferId,Title,Manager,Delivery )
AS
(
SELECT 4 , 'Offer1' , 'John Doe' , 'Service' Union All
SELECT 4 , 'Offer1' , 'John Doe' , 'Time' Union All
SELECT 4 , 'Offer1' , 'John Doe' , 'Material' Union All
SELECT 5 , 'Offer2' , 'Jane Doe' , 'Consulting' Union All
SELECT 5 , 'Offer2' , 'Jane Doe' , 'Time'
)
Select DISTINCT OfferId,Title,Manager,STUFF((SELECT DISTINCT ',' + CAST(i.Delivery AS VARCHAR(20)) FROM Cte_Convert i
WHERE i.OfferId=o.OfferId
FOR XML PATH ('')),1,1,'')AS Delivery
FROM Cte_Convert o
I Assume either above or below code might be useful
--Split Delivery column as comma separted in below Cte
;WITH Cte_Convert(OfferId,Title,Manager,Delivery )
AS
(
SELECT 4 , 'Offer1' , 'John Doe' , 'Service' Union All
SELECT 4 , 'Offer1' , 'John Doe' , 'Time' Union All
SELECT 4 , 'Offer1' , 'John Doe' , 'Material' Union All
SELECT 5 , 'Offer2' , 'Jane Doe' , 'Consulting' Union All
SELECT 5 , 'Offer2' , 'Jane Doe' , 'Time'
)
,Final
AS
(
SELECT ROW_NUMBER()OVER(Order by (SELECT ''))AS DeliveryVersionId ,* FROM
(
SELECT DISTINCT OfferId,Title,Manager,STUFF((SELECT DISTINCT ',' + CAST(i.Delivery AS VARCHAR(20)) FROM Cte_Convert i
WHERE i.OfferId=o.OfferId
FOR XML PATH ('')),1,1,'')AS Label
FROM Cte_Convert o
)dt
)
,BasicOffers(OfferId,Tile,Manager,DeliveryVersionId )
AS
(
SELECT 4 , 'Offer1' , 'John Doe' , 1 Union all
SELECT 5 , 'Offer2' , 'Jane Doe' , 2
)
,TmpLabels(DeliveryVersionId,Label)
AS
(
SELECT 1 , 'Service, Time, Material ' Union all
SELECT 2 , 'Consulting, Time'
)
Select B.OfferId,B.Tile,B.Manager, T.Label AS Delivery
From BasicOffers B
INNER JOIN Final T
ON T.DeliveryVersionId=B.DeliveryVersionId
I used temporary tables and Left outer join between them to solve it. Please note that I supposed that DeliveryVersionId is a primary Key in the #TmpLabels.
Please let me know if it helps you.
DECLARE #BasicOffers Table (
OfferId int,
Tile varchar(100),
Manager varchar(100),
DeliveryVersionId int)
insert into #BasicOffers values (4,'Offer1','John Doe',1)
insert into #BasicOffers values (5,'Offer2','Jane Doe',2)
DECLARE #TmpLabels Table (
DeliveryVersionId int,
Label varchar(100)
)
insert into #TmpLabels values (1,'Service, Time, Material')
insert into #TmpLabels values (2,'Consulting, Time')
Select OfferId, Tile, Manager, Label as Delivery
From #BasicOffers A Left Outer join
#TmpLabels B on A.DeliveryVersionId=B.DeliveryVersionId