简体   繁体   中英

MYSQL Selecting specific rows or first row if doesn't exist

I have a table of texts from various dates. Each is indexed by service, variation, and page and sub-page ids.

I need to fetch all entries for a given service, page and sub-page. ie each variation! BUT If the particular specific subpage doesn't exist, I need it to fetch the first subpage for that page, rather than nothing for that variation.

This is my code -

SELECT * FROM frames f
LEFT JOIN varients v ON f.varient_id = v.varient_id AND f.service_id = v.service_id
ẀHERE f.service_id = :sid 
AND f.frame_id = :fid 
AND (f.subframe_id = :subid 
    OR f.subframe_id = (
        select min(subframe_id) from frames ff 
        ẀHERE ff.service_id = f.service_id
            AND ff.varient_id = f.varient_id AND ff.frame_id = f.frame_id
            )
        )
GROUP BY f.service_id, f.varient_id, f.frame_id
ORDER BY f.service_id, v.varient_date, f.frame_id, f.subframe_id

but as often as not this just gives the minimum rather than the specific, even when the specific value exists. I'm pretty sure that the OR isn't what I need..

I've tried working with UNION as per some other answers, but since I want more than a single result, I can't seem to work it out!

Thanks for any help ..

OK. I managed to achieve what I wanted. Two days of messing with this, and finally work it out after posting a question. I was helped by one of the 'related' questions, which whilst not giving me an answer, made me think about it a different way -

I basically turned the whole thing inside out: As i only wanted one result per variation, I used that as the primary table. Then Joined the 'frames' table twice, once for the specific value, and once for the first value (found using a search for MIN().) Used IFNULL to return the second record if the first wasn;t found. An extra IS NOT NULL check against the second record within the WHERE to avoid returning anything where there is nothing stored against the variation record.

SELECT v.service_id, v.varient_id, IFNULL(f.frame_id,ff.frame_id)as frame_id,
        IFNULL(f.subframe_id,ff.subframe_id) as subframe_id , IFNULL(f.frameunique, ff.frameunique) as frameunique, IFNULL(f.frame_content,ff.frame_content) as framecontent
 FROM varients v
LEFT JOIN `frames` f ON `f`.`varient_id` = `v`.`varient_id` AND `f`.`service_id` = `v`.`service_id` AND  `f`.`frame_id` = 698 AND `f`.`subframe_id` = 0004
LEFT JOIN `frames` ff ON `ff`.`varient_id` = `v`.`varient_id` AND `ff`.`service_id` = `v`.`service_id` AND  `ff`.`frame_id` = 698
AND `ff`.`subframe_id` = (select min(`subframe_id`) from `frames` `fff` where `fff`.`service_id` = `v`.`service_id`
 AND `fff`.`varient_id` = `v`.`varient_id` AND `fff`.`frame_id` = 698 )

where `v`.`service_id` = 3 AND ff.frameunique IS NOT NULL
ORDER BY `f`.`service_id`, `v`.`varient_date`, `f`.`frame_id`, `f`.`subframe_id`

Posting this in case it helps anybody else. It still needs tidying but it works. Thanks for the comments. :)

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