Reputation: 117
Suppose I have the following tables:
vs_tblMovies
MOVIEID MOVIENAME
11 Star Wars
vs_tblGenreBridge
MOVIEID GENREID
11 878
11 28
11 12
vs_tblGenres
GENREID GENRETITLE
28 Action
12 Adventure
878 Science Fiction
vs_tblActors
ACTORID STAGELNAME STAGEFNAME
1 Lucas George
vs_tblCastMembers
CASTMEMBERROLEID MOVIEID ACTORID
351 11 1
352 11 1
353 11 1
vs_tblCastMemberRoles
CASTMEMBERROLEID CASTMEMBERROLETITLE CASTMEMBERROLEDESC
351 Directing Director
352 Production Executive Producer
353 Writing Writer
I want display all of the roles a given actor has had, with the result set being in the following format:
GENRETITLE MOVIENAME ACTORID STAGELNAME STAGEFNAME CASTMEMBERROLEID CASTMEMBERROLEDESC
To do this, I wrote the following query (getting the roles for ActorID = 1, which is George Lucas):
SELECT vs_tblGenres.GenreTitle,
vs_tblMovies.MovieName,
vs_tblActors.ActorID,
vs_tblActors.StageLName,
vs_tblActors.StageFName,
vs_tblCastMembers.CastMemberRoleID,
vs_tblCastMemberRoles.CastMemberRoleDesc
FROM vs_tblCastMembers
INNER JOIN vs_tblActors ON vs_tblCastMembers.ActorID = vs_tblActors.ActorID
INNER JOIN vs_tblMovies ON vs_tblCastMembers.MovieID = vs_tblMovies.MovieID
INNER JOIN vs_tblGenreBridge ON vs_tblMovies.MovieID = vs_tblGenreBridge.MovieID
INNER JOIN vs_tblGenres ON vs_tblGenreBridge.GenreID = vs_tblGenres.GenreID
INNER JOIN vs_tblCastMemberRoles ON vs_tblCastMembers.CastMemberRoleID = vs_tblCastMemberRoles.CastMemberRoleID
WHERE vs_tblActors.ActorID = 1
GROUP BY vs_tblGenres.GenreTitle,
vs_tblMovies.MovieName,
vs_tblActors.ActorID,
vs_tblActors.StageLName,
vs_tblActors.StageFName,
vs_tblCastMembers.CastMemberRoleID,
vs_tblCastMemberRoles.CastMemberRole Desc
Which Outputs:
| GENRETITLE | MOVIENAME | ACTORID | STAGELNAME | STAGEFNAME | CASTMEMBERROLEID | CASTMEMBERROLEDESC |
|-----------------|-----------|---------|------------|------------|------------------|--------------------|
| Science Fiction | Star Wars | 1 | Lucas | George | 352 | Executive Producer |
| Adventure | Star Wars | 1 | Lucas | George | 352 | Executive Producer |
| Action | Star Wars | 1 | Lucas | George | 351 | Director |
| Adventure | Star Wars | 1 | Lucas | George | 351 | Director |
| Science Fiction | Star Wars | 1 | Lucas | George | 353 | Writer |
| Science Fiction | Star Wars | 1 | Lucas | George | 351 | Director |
| Action | Star Wars | 1 | Lucas | George | 353 | Writer |
| Adventure | Star Wars | 1 | Lucas | George | 353 | Writer |
| Action | Star Wars | 1 | Lucas | George | 352 | Executive Producer |
What I want to do is to merge the cases where only the GenreTitle is different, so it doesn't list the role multiple times for each genre. The ideal ouput would be something like this:
| GENRETITLE | MOVIENAME | ACTORID | STAGELNAME | STAGEFNAME | CASTMEMBERROLEID | CASTMEMBERROLEDESC |
|------------------------------------|-----------|---------|------------|------------|------------------|--------------------|
| Action, Adventure, Science Fiction | Star Wars | 1 | Lucas | George | 352 | Executive Producer |
| Action, Adventure, Science Fiction | Star Wars | 1 | Lucas | George | 351 | Director |
| Action, Adventure, Science Fiction | Star Wars | 1 | Lucas | George | 353 | Writer |
What is the simplest way to do this in Oracle 12c?
Upvotes: 2
Views: 35
Reputation: 222432
You are almost there. All you have to do is pull out Oracle LISTAGG
aggregate function to agglutinate all GenreTitle
s together, with respect to other GROUP BY
fields. Accordingly, you need to remove GenreTitle
from the GROUP BY
clause.
From the docs :
For a specified measure, LISTAGG orders data within each group specified in the ORDER BY clause and then concatenates the values of the measure column.
Updated query :
SELECT LISTAGG(vs_tblGenres.GenreTitle, ', ') WITHIN GROUP (ORDER BY vs_tblGenres.GenreTitle) AS GenreTitle,
vs_tblMovies.MovieName,
vs_tblActors.ActorID,
vs_tblActors.StageLName,
vs_tblActors.StageFName,
vs_tblCastMembers.CastMemberRoleID,
vs_tblCastMemberRoles.CastMemberRoleDesc
FROM vs_tblCastMembers
INNER JOIN vs_tblActors ON vs_tblCastMembers.ActorID = vs_tblActors.ActorID
INNER JOIN vs_tblMovies ON vs_tblCastMembers.MovieID = vs_tblMovies.MovieID
INNER JOIN vs_tblGenreBridge ON vs_tblMovies.MovieID = vs_tblGenreBridge.MovieID
INNER JOIN vs_tblGenres ON vs_tblGenreBridge.GenreID = vs_tblGenres.GenreID
INNER JOIN vs_tblCastMemberRoles ON vs_tblCastMembers.CastMemberRoleID = vs_tblCastMemberRoles.CastMemberRoleID
WHERE vs_tblActors.ActorID = 1
GROUP BY vs_tblMovies.MovieName,
vs_tblActors.ActorID,
vs_tblActors.StageLName,
vs_tblActors.StageFName,
vs_tblCastMembers.CastMemberRoleID,
vs_tblCastMemberRoles.CastMemberRole Desc
Upvotes: 1