Two different concatenates based on the same table

94 views Asked by At

I try to design a mysql query to get results from a Greek movie database like: Title, concatenated Directors and concatenated awarded people. So, I use:

SELECT 
     `MT_films`.`ID_films` AS `ID_films`,
    `ST_br_persons`.`etos_brp` AS `year_award`,  
    `T_brab_p`.`brabeio_p` AS `price`,
    `T_thesmos`.`thesmos` AS `festival`,
    `T_idiotita`.`idiotita` AS `specialty`,
    CONCAT('<a href="./index.php/search-movies/titlededj?id_films=',
            `MT_films`.`ID_films`,
            '">',
            `MT_films`.`Title1`,
            '</a>') AS `movie`,
    GROUP_CONCAT(DISTINCT '<a href="./index.php/search-movies/peoplefilm?person=',
        `ST_br_persons`.`ID_person`,
        '">',
        `T_people`.`person`,
        '</a>'
        SEPARATOR ', ') AS `awarded_person`,
    GROUP_CONCAT(CASE
            WHEN
                `ST_peoplefilms`.`ID_idiotita` = 29 --> director specialty filter
            THEN
                CONCAT('<a href="./index.php/search-movies/peoplefilm?person=',
                        `ST_peoplefilms`.`ID_person`,
                        '">',
                        `T_people`.`person`,
                        '</a>')
        END
        SEPARATOR ', ') AS `Director`
FROM
    (((((((`T_people` `T_people_1`
    JOIN `ST_peoplefilms` `ST_peoplefilms_1` ON (`T_people_1`.`ID_person` = `ST_peoplefilms_1`.`ID_person`))
    JOIN `MT_films` ON (`MT_films`.`ID_films` = `ST_peoplefilms_1`.`ID_films`))
    JOIN `ST_br_persons` ON (`ST_br_persons`.`ID_person` = `T_people_1`.`ID_person`))
    JOIN `T_idiotita` ON (`T_idiotita`.`ID_idiotita` = `ST_br_persons`.`ID_Idiotita`))
    JOIN `T_thesmos` ON (`T_thesmos`.`ID_thesmos` = `ST_br_persons`.`ID_thesmos`))
    JOIN `T_brab_p` ON (`T_brab_p`.`ID_brab_p` = `ST_br_persons`.`ID_brabeio`))
    JOIN `T_people` ON (`T_people`.`ID_person` = `ST_br_persons`.`ID_person`))
WHERE
    `ST_br_persons`.`ID_thesmos` IN (12 , 270, 446, 447, 448, 449, 565, 566)
        AND `ST_br_persons`.`ID_Films` = `ST_peoplefilms_1`.`ID_films`
        AND `MT_films`.`ID_films` = 12429


GROUP BY `ST_br_persons`.`ID_brabeio` , `ST_br_persons`.`ID_Films`
ORDER BY `ST_br_persons`.`year_award`

Obviously all films have a director and in some of them there are award-winning persons from other qualities e.g. Screenplay award, scenography award etc etc...

Query works fine for all the awarded people, but the problem is that it returns null in the director's field.

ID_films year_award price Festival movie awarded_person Director
2677 2021 Best scenery DISFF IF I KNEW John null
2678 2023 Best actress AAISFF LOVEHATERS Eva, Georgia null
13459 1985 Best scenography FFGR CAT POSTALE Steve, Maria, Kostas null

But when the director of a film is awarded with the Best director's award then the Director field displays his name normally

ID_films year_award price Festival movie awarded_person Director
13741 2020 Best directing xxx1 BASTARDS Panos Panos
11213 2012 Best directing xxx2 LISTEN Chris, Liza Chris, Liza
1256 2015 Best directing xxx3 CAT POSDODO Katerina Katerina

Desired outcome

ID_films year_award price Festival movie awarded_person Director
2677 2021 Best scenery DISFF IF I KNEW John Kostas
2678 2023 Best actress AAISFF LOVEHATERS Eva, Georgia Yiannis
13459 1985 Best scenography FFGR CAT POSTALE Steve, Maria, Kostas Alexis, Vangelis
1

There are 1 answers

0
user1191247 On BEST ANSWER

Because the director of a film may, or may not, be in the list of awarded_people, they may, or may not, be joined via st_br_persons. And, because there may be multiple directors and awarded_people, adding another join to get the director(s) could result in a cartesian product between the two. Instead I have retrieved the director(s) with a correlated subquery in the select list. I have also added the additional columns to the GROUP BY clause to make the query valid (read MySQL Handling of GROUP BY). I have also removed aa_st_br_person from the select list as it did not make sense as a row can aggregate multiple awarded people. To make it valid you would either need to use an aggregate function or add it to the GROUP BY clause.

SELECT 
    f.ID_films,
    br_p.etos_brp AS year_award,
    b.brabeio_p AS award,
    t.thesmos AS festival,
    f.Title1 AS movie,
    GROUP_CONCAT(p.ID_person, '::', p.person SEPARATOR '||') AS awarded_people,
    (
        SELECT GROUP_CONCAT(p.ID_person, '::', p.person SEPARATOR '||')
        FROM t_people p
        JOIN st_peoplefilms pf ON p.ID_person = pf.ID_person AND pf.ID_idiotita = 29
        WHERE pf.ID_films = f.ID_films
    ) AS director
FROM st_br_persons br_p
JOIN t_people p
    ON br_p.ID_person = p.ID_person
JOIN mt_films f
    ON br_p.ID_films = f.ID_films
JOIN t_thesmos t
    ON br_p.ID_thesmos = t.ID_thesmos
JOIN t_brab_p b
    ON br_p.ID_brabeio = b.ID_brab_p

WHERE br_p.ID_thesmos IN (12 , 270, 446, 447, 448, 449, 565, 566)
  
GROUP BY
    br_p.ID_brabeio,
    br_p.etos_brp,
    br_p.ID_Films,
    br_p.ID_thesmos
ORDER BY br_p.etos_brp DESC;

Output:

ID_films year_award award festival movie awarded_people director
14365 2023 Screenplay Award DISFF National Competition AEROLIN 34980::Koukias Pantelis Alexis||43644::Mathioudakis Michalis 34980::Koukias Pantelis Alexis
14365 2023 Direction Award DISFF National Competition AEROLIN 34980::Koukias Pantelis Alexis 34980::Koukias Pantelis Alexis
12429 2021 Scenography Award DISFF National Competition BRUTALIA, DAYS OF LABOUR 18238::Kalogianni Dafni 36433::Mavris Manolis
12429 2021 Costume Design Award DISFF National Competition BRUTALIA, DAYS OF LABOUR 36437::Gioulakou Eva 36433::Mavris Manolis

Here's a db<>fiddle to play with.