Search code examples
sql

Can the number of intermediate results rows be limited in a simple multi-table join?


I'm trying to use a LEFT JOIN to pull information into one table from two others. It works for most instances because each table has at most one match per row of the primary table. However, in some instances the third table has more than one match but the data column from that table is the same for each match.

A GROUP BY at the end removes the duplicates; but is there a smarter way of somehow adding something to the join with table t3 to limit it to 1 row?

Thank you.

create table t1 (doc_id, track_id, timestamp);
create table t2 (doc_id, timestamp, starttime);
create table t3 (track_id, chapter, title);

insert into t1 
values (1, '05009', 173), (2, '07290', 174), (3, '08002', 175); 
insert into t2 
values (1, 173, '02:05'), (2, 174, '05:17'), (3, 175, '10:35'); 
insert into t3 
values ('08002', 1, 'title 08002'), ('05009', 2, 'title 05009'),('05009', 3, 'title 05009');

select
    t1.*, t2.starttime, t3.title
from
    t1
left join
    t2 on (t1.doc_id,t1.timestamp) = (t2.doc_id,t2.timestamp)
left join
    t3 on t1.track_id = t3.track_id;

/*
doc_id  track_id  timestamp  starttime  title      
------  --------  ---------  ---------  -----------
1       05009     173        02:05      title 05009
1       05009     173        02:05      title 05009
2       07290     174        05:17      NULL       
3       08002     175        10:35      title 08002
*/

select
    t1.*, t2.starttime, t3.title
from
    t1
left join
    t2 on (t1.doc_id,t1.timestamp) = (t2.doc_id,t2.timestamp)
left join
    t3 on t1.track_id = t3.track_id
group by
    t1.track_id;

/*
doc_id  track_id  timestamp  starttime  title      
------  --------  ---------  ---------  -----------
1       05009     173        02:05      title 05009
2       07290     174        05:17      NULL       
3       08002     175        10:35      title 08002
*/

Solution

  • Don't join with t3, join with a subquery that gets the unique values you care about. So change

    left join t3
    

    to

    left join (
        SELECT DISTINCT track_id, title
        FROM t3
    ) AS t3
    

    If the title is always the same regardless of the chapter, this also suggests that your database is not properly normalized. t3 should be split into two tables:

    CREATE TABLE t3a (track_id, title, PRIMARY KEY (track_id));
    CREATE TABLE t3b (track_id, chapter, 
        PRIMARY KEY (track_id, chapter), 
        FOREIGN KEY (track_id) REFERENCES t3a (track_id));
    

    Then you would just join with t3a to get your desired result.