Solved

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

Posted on 2010-11-09
14
234 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
Free eBook: Backup on AWS

Everything you need to know about backup and disaster recovery with AWS, for FREE!

 
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

Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

Question has a verified solution.

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

Occasionally there is a need to clean table columns, especially if you have inherited legacy data. There are obviously many ways to accomplish that, including elaborate UPDATE queries with anywhere from one to numerous REPLACE functions (even within…
This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…

695 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