Solved

T-SQL Query needed for double-level string concatination from a single table

Posted on 2010-11-09
14
233 Views
Last Modified: 2012-05-10
For Microsoft SQL Server 2005 T-SQL I'm having difficulty writing a query that concatenates two-levels such as Compact Disc discs and tracks (see table below).

My best attempt is using XML as a vehicle for string concatenation as described here.

Using a single query without a server-side cursor I'd like to generate a report of my music collection like below with one concatenated line output per database row per album.  Once I figure out the query I'll add the appropriate HTML as a detail.

OUTPUT ROW 1:

Album 1
  Disc 1
    1. She Loves You
    2. Yellow Submarine

  Disc 2
    1. Revolution
    2. Long and Winding Road
    3. Hey Jude


OUTPUT ROW 2:

Album 2
  Disc 1
    ...


OUTPUT ROW 3:

Album 3
  Disc 1
     ....

  Disc 2
    .....
create table Song (
  AlbumID int,
  DiscNbr tinyint,
  TrackNbr tinyint,
  Song varchar(50)
)

Open in new window

0
Comment
Question by:ZuZuPetals
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 2
14 Comments
 
LVL 3

Expert Comment

by:expert_dharam
ID: 34095404
Did u tried this..

select AlbumID, STUFF(
      (SELECT  ',' + a.Song  AS [text()]
      from Song  a
      where a.AlbumID = b.AlbumID
      Order by a.Song
      for xml PATH('')),1,1,''      ) AS Comments_Concatenated
 from Song b
group by AlbumID
ORDER BY AlbumID
0
 
LVL 2

Author Comment

by:ZuZuPetals
ID: 34095689
Yes, but that's one level.
0
 
LVL 3

Expert Comment

by:expert_dharam
ID: 34095933
Here you go..

SELECT AlbumID, DiscNbr,

STUFF(
      (SELECT  ', ' + cast(a.TrackNbr as varchar) + '.' + a.Song  AS [text()]
      FROM Song  a
      WHERE a.AlbumID = b.AlbumID and a.DiscNbr = b.DiscNbr
      Order by a.Song
      FOR XML PATH('')),1,1,''      ) AS Songs
      
      
 FROM Song b
group by AlbumID,DiscNbr
ORDER BY AlbumID,DiscNbr
0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
LVL 2

Author Comment

by:ZuZuPetals
ID: 34097195
Thanks expert_dharam... that's a partial solution: that creates one row per disc.    Now I'm trying to caress it to roll up all discs of an album to a single row.
0
 
LVL 51

Expert Comment

by:Mark Wills
ID: 34099464
How about something like :


select ',' + 'Album '+convert(varchar,a.albumid) + ',' +
       'Disc '+convert(varchar,a.Discnbr) +
       (select ',' + convert(varchar,Tracknbr) + '.' + Song
        from song b where a.albumid = b.albumid and a.discnbr = b.discnbr for xml path('')) as [text()]
from (select distinct albumid, Discnbr from song) a  
for xml path('')
0
 
LVL 51

Expert Comment

by:Mark Wills
ID: 34099476
Think I might be misunderstanding your output requirement... Treated it as one long concatenated string.

Thats not quite what you are after - is it...

0
 
LVL 51

Expert Comment

by:Mark Wills
ID: 34099553
What about....


select listing
from (
      select albumid,0 as discnbr, 0 as tracknbr, 'Album '+convert(varchar,albumid) as listing from song group by albumid
      union
      select albumid,discnbr, 0 as tracknbr, '     Disc '+convert(varchar,Discnbr) as listing from song group by albumid, discnbr
      union
      select albumid,discnbr, tracknbr, '          '+convert(varchar,tracknbr)+'. '+song as listing from song
     )s
order by albumid,discnbr, tracknbr


0
 
LVL 2

Author Comment

by:ZuZuPetals
ID: 34105602
@mark_wills: The first one concatenates to a single string and the second one does no concatenation.  Still looking for something in between (one row per album), but I appreciate the attempts.
0
 
LVL 51

Expert Comment

by:Mark Wills
ID: 34106926
Right, knew I was misunderstanding :D

how about :

select 'Album '+convert(varchar,a.albumid) +
       (select ','+'Disc '+convert(varchar,Discnbr) +',' + convert(varchar,Tracknbr) + '.' + Song
        from song b where a.albumid = b.albumid for xml path('')) as [text()]
from (select distinct albumid from song) a  
0
 
LVL 2

Author Comment

by:ZuZuPetals
ID: 34113510
@mark_willis: Wow, that's really close.  The only bad thing is that it repeats the disc number for every track.
0
 
LVL 2

Author Comment

by:ZuZuPetals
ID: 34113560
My solution that I implemented is to use XML/text() to encapsulate the "tracks per disc" concatenation into a view for simplicity and readability.  I then use that view in a second XML/text() to concatenate the "discs per album" into a single string.  It takes 10 minutes to run on a million records but produces the exact result specified in the problem statement.  Thanks for everyone's help.
0
 
LVL 51

Accepted Solution

by:
Mark Wills earned 500 total points
ID: 34113837
Ah well... Good to hear you got your solution...

FWIW here is my last attempt (it is a challenge now) :)


select 'Album '+convert(varchar,a.albumid) +
    (select ','+'Disc '+convert(varchar,D.Discnbr) +
        (select ',' + convert(varchar,Tracknbr) + '.' + Song from song b where a.albumid = b.albumid and d.Discnbr=b.Discnbr for xml path(''))
    from song d where a.albumid=d.albumid group by d.discnbr for xml path(''))
from (select distinct albumid from song) a
0
 
LVL 2

Author Comment

by:ZuZuPetals
ID: 34114895
Awesome!!! That's it!  You did it Mark!  Thanks!

The only thing I added was order by DiscNbr,TrackNbr to get the ordering 1, 2, 3, etc. ascending.
0
 
LVL 2

Author Closing Comment

by:ZuZuPetals
ID: 34114898
YOU ROCK!
0

Featured Post

U.S. Department of Agriculture and Acronis Access

With the new era of mobile computing, smartphones and tablets, wireless communications and cloud services, the USDA sought to take advantage of a mobilized workforce and the blurring lines between personal and corporate computing resources.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I'm trying, I really am. But I've seen so many wrong approaches involving date(time) boundaries I despair about my inability to explain it. I've seen quite a few recently that define a non-leap year as 364 days, or 366 days and the list goes on. …
Composite queries are used to retrieve the results from joining multiple queries after applying any filters. UNION, INTERSECT, MINUS, and UNION ALL are some of the operators used to get certain desired results.​
This video shows how to use Hyena, from SystemTools Software, to update 100 user accounts from an external text file. View in 1080p for best video quality.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question