Solved

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

Posted on 2010-11-09
14
228 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
  • 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
 
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
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: 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Hi all, It is important and often overlooked to understand “Database properties”. Often we see questions about "log files" or "where is the database" and one of the easiest ways to get general information about your database is to use “Database p…
PL/SQL can be a very powerful tool for working directly with database tables. Being able to loop will allow you to perform more complex operations, but can be a little tricky to write correctly. This article will provide examples of basic loops alon…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
I designed this idea while studying technology in the classroom.  This is a semester long project.  Students are asked to take photographs on a specific topic which they find meaningful, it can be a place or situation such as travel or homelessness.…

948 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now