lundi 29 juin 2015

Alternative To Huge Result Set From Multiple LEFT JOINs

I'm seeking some advice on handling scenarios where the number of rows in a result set explodes when you LEFT JOIN multiple tables. I understand this is expected behavior, but I’d like to know the recommended way to handle it. I know I can have my application perform multiple queries to reduce the number of rows returned overall, but I am trying to see if there is a way to have SQL do most of the heavy lifting and still make only one “round trip” (e.g., a la this answer).

Example

Here’s my SQL:

SELECT al.title albumTitle
    , releaseDate
    , name artistName
    , duration
    , t.title trackTitle
    , styleName
FROM album al
LEFT JOIN lu_albumartist aa ON aa.albumId = al.albumId
LEFT JOIN artist ar ON ar.artistId = aa.artistId
LEFT JOIN track t ON t.albumId = al.albumId
LEFT JOIN lu_albumstyle ast ON ast.albumId = al.albumId
LEFT JOIN style s ON s.styleId = ast.styleId
WHERE al.title LIKE '%A Love Supreme%'

This SQL Fiddle helps demonstrate the problem:

I am retrieving information on a music album. I really only need 11 rows to be able to have my app populate all fields (1 album, 4 artists, 3 tracks, 3 styles), but the query pulls back 36 rows. I won't be able to use most rows; for example, I don’t care about all the permutations of styles & artists or styles & tracks. When I add even more LEFT JOINS for other things (e.g., instruments, formats, comments, track play info, etc.) the number of permutations can expand into the 10,000s!

Ideally, what I'd like is a result set that’s more concise:

Super Compact: 4 rows (doesn't make much sense to read the table this way, though the application could parse it)

|          title |                releaseDate |           name |    duration |                                  title |   styleName |
|----------------|----------------------------|----------------|-------------|----------------------------------------|-------------|
| A Love Supreme |                       1965 |  John Coltrane |         479 |               Part I - Acknowledgement |   Free Jazz |
|    [something] |                [something] |    McCoy Tyner |         435 |                   Part II - Resolution |    Hard Bop |
|    [something] |                [something] | Jimmy Garrison |        1060 | Part III - Pursuance / Part IV - Psalm |       Modal |
|    [something] |                [something] |    Elvin Jones | [something] |                            [something] | [something] |

..."[something]" just means the value can be anything; the app won't care

Compact: 11 rows (makes sense to humans)

|          title |                releaseDate |           name | duration |                                  title | styleName |
|----------------|----------------------------|----------------|----------|----------------------------------------|-----------|
| A Love Supreme |                       1965 |                |          |                                        |           |
|                |                            |  John Coltrane |          |                                        |           |
|                |                            |    McCoy Tyner |          |                                        |           |
|                |                            | Jimmy Garrison |          |                                        |           |
|                |                            |    Elvin Jones |          |                                        |           |
|                |                            |                |      479 |               Part I - Acknowledgement |           |
|                |                            |                |      435 |                   Part II - Resolution |           |
|                |                            |                |     1060 | Part III - Pursuance / Part IV - Psalm |           |
|                |                            |                |          |                                        | Free Jazz |
|                |                            |                |          |                                        | Hard Bop  |
|                |                            |                |          |                                        |     Modal |

I'm less concerned about performance than my app's code portability, readability, & scalability.

Based on that earlier linked question, the other answers and comments suggested I shouldn’t attempt to join more than 3 tables.

  1. Should I just give up on this approach? If I were to use multiple queries, there could be a dozen or more.
  2. I suspect there is a way to solve this with UNION ALLs, but is that the best practice?
  3. I'm guessing this is a relatively common problem, but I couldn't find a good answer or a set of guidelines to follow. What’s the recommended approach for this situation?

Aucun commentaire :

Enregistrer un commentaire