简体   繁体   中英

Selecting distinct rows based on values from left table

Using Postgres. Here's my scenario:

I have three different tables. One is a title table. The second is a genre table. The third table is used to join the two. When I designed the database, I expected that each title would have one top level genre. After filling it with data, I discovered that there were titles that had two, sometimes, three top level genres.

I wrote a query that retrieves titles and their top level genres. This obviously requires that I join the two tables. For those that only have one top level genre, there is one record. For those that have more, there are multiple records.

I realize I'll probably have to write a custom function of some kind that will handle this for me, but I thought I'd ask if it's possible to do this without doing so just to make sure I'm not missing anything.

Is it possible to write a query that will allow me to select all of the distinct titles regardless of the number of genres that it has, but also include the genre? Or even better, a query that would give me a comma delimited string of genres when there are multiples?

Thanks in advance!

Sounds like a job for array_agg to me. With tables like this:

create table t  (id int not null, title varchar not null);
create table g  (id int not null, name varchar not null);
create table tg (t int not null, g int not null);

You could do something like this:

SELECT t.title, array_agg(g.name)
FROM t, tg, g
WHERE t.id = tg.t
  AND tg.g = g.id
GROUP BY t.title, t.id

to get:

 title |       array_agg       
-------+-----------------------
 one   | {g-one,g-two,g-three}
 three | {g-three}
 two   | {g-two}

Then just unpack the arrays as needed. If for some reason you really want a comma delimited string instead of an array, then string_agg is your friend:

SELECT t.title, string_agg(g.name, ',')
FROM t, tg, g
WHERE t.id = tg.t
  AND tg.g = g.id
GROUP BY t.title, t.id

and you'll get something like this:

 title |     string_agg      
-------+---------------------
 one   | g-one,g-two,g-three
 three | g-three
 two   | g-two

I'd go with the array approach so that you wouldn't have to worry about reserving a character for the delimiter or having to escape (and then unescape) the delimiter while aggregating.

看看这个可能回答你问题的帖子

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM