SQL Pivot and String Concatenation Aggregate

Sql PIVOT and string concatenation aggregate

In order to get the result, first you should concatenate the values into the comma separated list.

I would use CROSS APPLY and FOR XML PATH:

SELECT distinct e.[Event Name],
e.[Resource Type],
LEFT(r.ResourceName , LEN(r.ResourceName)-1) ResourceName
FROM yourtable e
CROSS APPLY
(
SELECT r.[Resource Name] + ', '
FROM yourtable r
where e.[Event Name] = r.[Event Name]
and e.[Resource Type] = r.[Resource Type]
FOR XML PATH('')
) r (ResourceName)

See SQL Fiddle with Demo. The gives you result:

| EVENT NAME |   RESOURCE TYPE |                          RESOURCENAME |
------------------------------------------------------------------------
| Event 1 | Resource Type 1 | Resource 1, Resource 2 |
| Event 1 | Resource Type 2 | Resource 3, Resource 4 |
| Event 1 | Resource Type 3 | Resource 5, Resource 6, Resource 7 |
| Event 1 | Resource Type 4 | Resource 8 |
| Event 2 | Resource Type 2 | Resource 3 |
| Event 2 | Resource Type 3 | Resource 11, Resource 12, Resource 13 |
| Event 2 | Resource Type 4 | Resource 14 |
| Event 2 | Resource Type 5 | Resource 1, Resource 9, Resource 16 |

Then you will apply your PIVOT to this result:

SELECT [Event Name],
[Resource Type 1], [Resource Type 2],
[Resource Type 3], [Resource Type 4],
[Resource Type 5]
FROM
(
SELECT distinct e.[Event Name],
e.[Resource Type],
LEFT(r.ResourceName , LEN(r.ResourceName)-1) ResourceName
FROM yourtable e
CROSS APPLY
(
SELECT r.[Resource Name] + ', '
FROM yourtable r
where e.[Event Name] = r.[Event Name]
and e.[Resource Type] = r.[Resource Type]
FOR XML PATH('')
) r (ResourceName)
) src
pivot
(
max(ResourceName)
for [Resource Type] in ([Resource Type 1], [Resource Type 2],
[Resource Type 3], [Resource Type 4],
[Resource Type 5])
) piv

See SQL Fiddle with Demo. Your final result will then be:

| EVENT NAME |        RESOURCE TYPE 1 |        RESOURCE TYPE 2 |                       RESOURCE TYPE 3 | RESOURCE TYPE 4 |                     RESOURCE TYPE 5 |
----------------------------------------------------------------------------------------------------------------------------------------------------------------
| Event 1 | Resource 1, Resource 2 | Resource 3, Resource 4 | Resource 5, Resource 6, Resource 7 | Resource 8 | (null) |
| Event 2 | (null) | Resource 3 | Resource 11, Resource 12, Resource 13 | Resource 14 | Resource 1, Resource 9, Resource 16 |

SQL Server pivot with string concatenation

I have concatenated the answer list first per name and subject, then applied pivoting -

declare @temp table (name varchar(100), subject varchar(100), answer varchar(100))

insert into @temp
select 'Pranesh','Physics' ,'Numerical Problems'
union all select 'Pranesh','Physics' ,'Other'
union all select 'Pranesh','Chemistry','Understanding Concepts'
union all select 'Pranesh','Chemistry','Organic chemistry reactions'
union all select 'Pranesh','Maths' ,'Lack of understanding'
union all select 'Pranesh','Maths' ,'Insufficient practice'
union all select 'Pranesh','Maths' ,'Other'
union all select 'Ramesh','Biology' , 'Other'
union all select 'Ramesh','Biology' , 'Science'

;with cte as (select distinct name, subject from @temp)
select * from
(
select
c.name,
c.subject,
answer = stuff((select ',' + answer from @temp t where t.name=c.name and t.subject=c.subject for xml path('')), 1, 1, '')
from cte c
) src
pivot
(
max(answer) for subject in ([Physics], [Chemistry], [Maths], [Biology],[ComputerScience],[CommonUnderstanding])
) piv

SQL aggregate function against concatenated string in pivot table

Cast [Status] and [Location] to a varchar performing the concatenation. I have arbitrarily chosen 3 as the length of the varchar but that may vary depending on what your maximum possible [Status] and [Location] are.

Also, remove the [Status] and [Location] columns from the inner query.

SELECT *
FROM (
SELECT
empId,
left(datename(dd,[Date]),2)as [day_date],
cast([Status] AS varchar(3)) + '|' + cast([Location] as varchar(3)) as val
FROM [dbo].[table]
WHERE [date] BETWEEN '2014-01-01' AND '2014-01-30') as s
PIVOT (MAX(val) FOR [day_date] IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31])
)AS p
order by empID

Amazon Redshift Pivot using Concatenation

You can use conditional aggregation:

SELECT 
foo_id,
MAX(CASE WHEN country = 'US' THEN foo_value END) AS US,
MAX(CASE WHEN country = 'IN' THEN foo_value END) AS "IN",
MAX(CASE WHEN country = 'DE' THEN foo_value END) AS DE
FROM mytable
GROUP BY foo_id

How to use GROUP BY to concatenate strings in SQL Server?

No CURSOR, WHILE loop, or User-Defined Function needed.

Just need to be creative with FOR XML and PATH.

[Note: This solution only works on SQL 2005 and later. Original question didn't specify the version in use.]

CREATE TABLE #YourTable ([ID] INT, [Name] CHAR(1), [Value] INT)

INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'A',4)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'B',8)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)

SELECT
[ID],
STUFF((
SELECT ', ' + [Name] + ':' + CAST([Value] AS VARCHAR(MAX))
FROM #YourTable
WHERE (ID = Results.ID)
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,2,'') AS NameValues
FROM #YourTable Results
GROUP BY ID

DROP TABLE #YourTable

SQL Server error using the CONCAT function in a pivot aggregated function

Try this,

CREATE TABLE #PIVOT (Time  DATETIME, AREA INT, BLOBs INT, CARs VARChar (10))

insert into #PIVOT values
('2018-05-07 16:00:00.000', 02, 11 ,'BMW')
,('2018-05-07 16:15:00.000', 02, 2 ,'BMW')
,('2018-05-07 16:15:00.000', 06, 7 ,'KIA')
,('2018-05-07 16:30:00.000', 06, 8 ,'KIA')
,('2018-05-07 16:45:00.000', 02, 9 ,'BMW')
,('2018-05-07 17:00:00.000', 02, 9 ,'BMW')
,('2018-05-07 17:00:00.000', 10, 8 ,'FIA')


select
Time, CARs + convert (varchar (10), [02]) [02]
, CARs + convert (varchar (10), [06]) [06], CARs + convert (varchar (10), [10]) [10]
from (
select
*
from #PIVOT
) p
pivot
(
max (BLOBs) for area in ([02],[06], [10])
) t

Time 02 06 10
2018-05-07 16:00:00.000 BMW11 NULL NULL
2018-05-07 16:15:00.000 BMW2 NULL NULL
2018-05-07 16:45:00.000 BMW9 NULL NULL
2018-05-07 17:00:00.000 BMW9 NULL NULL
2018-05-07 17:00:00.000 NULL NULL FIA8
2018-05-07 16:15:00.000 NULL KIA7 NULL
2018-05-07 16:30:00.000 NULL KIA8 NULL

Let me work for dynamic query.

Is there a way to take this data, pivot it and then combine it into a single string..?

To get the first column you're after:

; -- see sqlblog.org/cte
WITH src AS
(
SELECT num, [module-id], txt = STUFF(
(SELECT CONCAT(' & ', 'p-', [page-no], ' ', txt)
FROM dbo.StuffAndThings WHERE num = s.num
AND [module-id] = s.[module-id]
FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'varchar(max)'), 1, 3, '')
FROM dbo.StuffAndThings AS s
WHERE [page-no] = 1
)
SELECT num,
[module-id-1] = [1],
[module-id-2] = [2],
[module-id-3] = [3]
FROM src PIVOT
(MAX(txt) FOR [module-id] IN ([1],[2],[3])) AS p;
  • Example db<>fiddle

How to aggregate and string concatenate at same time in Oracle?

Would this do?

SQL> with test (customer, product, amount) as
2 (select 'a', 'table', 500 from dual union all
3 select 'a', 'table', 300 from dual union all
4 select 'a', 'chair', 100 from dual union all
5 select 'b', 'rug' , 50 from dual union all
6 select 'b', 'chair', 200 from dual
7 )
8 select customer,
9 listagg (product, ', ') within group (order by null) product,
10 sum(sum_amount) amount
11 from (select customer, product, sum(amount) sum_amount
12 from test
13 group by customer, product
14 )
15 group by customer
16 order by customer;

C PRODUCT AMOUNT
- -------------------- ----------
a chair, table 900
b chair, rug 250

SQL>

How to concatenate text from multiple rows into a single text string in SQL Server

If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.

I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH method can handle the concatenation of the rows very easily.

If there is a table called STUDENTS

SubjectID       StudentName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward

Result I expected was:

SubjectID       StudentName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward

I used the following T-SQL:

SELECT Main.SubjectID,
LEFT(Main.Students,Len(Main.Students)-1) As "Students"
FROM
(
SELECT DISTINCT ST2.SubjectID,
(
SELECT ST1.StudentName + ',' AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)') [Students]
FROM dbo.Students ST2
) [Main]

You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring to skip the first one so you don't need to do a sub-query:

SELECT DISTINCT ST2.SubjectID, 
SUBSTRING(
(
SELECT ','+ST1.StudentName AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH (''), TYPE
).value('text()[1]','nvarchar(max)'), 2, 1000) [Students]
FROM dbo.Students ST2


Related Topics



Leave a reply



Submit