3

I have a query that searches through several tables and returns one row for every value in one specific column of one of the queried tables. The table returns multiple rows for one unique identifier. What I want to do is combine those rows that have the same unique identifier and combine 2 of the column's value separated by commas and return those values as a unique column.

Example:

 Museum     MuseumID     Country     City     Paintings     Sculptures

 Louvre     345          France      Paris    Mona Lisa     NULL
 Louvre     345          France      Paris    NULL          Venus De Milo
 Louvre     345          France      Paris    Ship of Fools NULL

Instead I would like to make the query do this:

 Museum     MuseumID     Country     City     Art
 Louvre     345          France      Paris    Mona Lisa, Venus De Milo, Ship of Fools

I need to turn this query into a stored procedure that can be used in a C# program. At first I just took the data as is and used C# to combine the rows using arrays and some logic but I HAVE TO make this a stored procedure instead to make the data come over to the C# program already sorted and combined. I don't want to I have to. I need help.

Can anyone help with this?

broguyman
  • 1,386
  • 4
  • 19
  • 36
  • possible duplicate of [Concatenate grouped rows](http://stackoverflow.com/questions/9139472/concatenate-grouped-rows) – Tony Feb 27 '12 at 22:06

2 Answers2

3

Given this sample data:

CREATE TABLE #a
(
    Museum     varchar(32),
    MuseumID   int, 
    Country    varchar(32),
    City       varchar(32),
    Paintings  varchar(32),
    Sculptures varchar(32)
);

INSERT #a VALUES
('Louvre',345,'France','Paris', 'Mona Lisa',     NULL),
('Louvre',345,'France','Paris', NULL,            'Venus De Milo'),
('Louvre',345,'France','Paris', 'Ship of Fools', NULL);

In older versions of SQL Server, we'd have to perform grouped string aggregation using a derived table that munged strings together using FOR XML PATH:

SELECT Museum, MuseumID, Country, City, 
    Art = STUFF((SELECT ', ' + COALESCE(Paintings, Sculptures, '')
    FROM #a AS a2
    WHERE a2.museum = a.museum AND a2.MuseumID = a.MuseumID
    AND a2.Country = a.Country AND a2.City = a.City
    FOR XML PATH(''), 
    TYPE).value(N'./text()[1]', N'varchar(max)'), 1,2,'')
FROM #a AS a
GROUP BY Museum, MuseumID, Country, City;

In SQL Server 2017+, we can use STRING_AGG() for a much simpler and more efficient query:

SELECT Museum, MuseumID, Country, City,
  Art = STRING_AGG(COALESCE(Paintings, Sculptures, ''), ', ')
FROM #a
GROUP BY Museum, MuseumID, Country, City;

Results in both cases:

Museum MuseumID Country City Art
Louvre 345 France Paris Mona Lisa, Venus De Milo, Ship of Fools

(Note that if a painting or sculpture name has a comma in it, which is probably not rare, you won't be able to tell. So sometimes it is better to choose a delimiter that has a really low probability of being in the data, like a pipe ('|') or use nvarchar as the base type and some Unicode character like double pipe (N'‖').)

Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
1

According to this you should use COALESCE .

I would first unite the Paintings and Sculptures columns into one column called OneArt (in your first query), then use COALESCE on it and a GROUP BY MuseumID.

Community
  • 1
  • 1
zmbq
  • 38,013
  • 14
  • 101
  • 171