Question

I'm not very good at joins with lots of tables, having trouble putting this into SQLite. I have a database with these tables:

Feeds->Channels->RegionsChannels->Regions.

where Channels can have 0 or more connections to Regions through RegionsChannels.

Regions has a boolean field (0, 1) that indicates whether or not the user has enabled this region.

I want to get some fields from Feeds, say, Feeds.id and Feeds.title for all the feeds that contain channels that either have no connection to Regions or have a connection to Regions where Regions.selected = 1;

I tried joining all the tables together like this:

select feeds.feed_id, feeds.title
from feeds
    left outer join channels on feeds.feed_id = channels.feed_id
    left outer join regions_channels on channels.channel_id = regions_channels.channel_id
    left outer join regions on regions_channels.region_id = regions.region_id
        and regions.selected = 1
group by feeds.feed_id
order by feeds.feed_id;

trying to get only the selected regions but it just gave me back all the feeds anyway. I thought maybe I should be doing a RIGHT OUTER JOIN on the regions table but I'm using SQLite and it doesn't support RIGHT or FULL OUTER JOINs.

UPDATE:

I just tried this and I am getting exactly what I want, I have toggled several regions.selected and it comes back good every time. But I have no idea if it REALLY works or if it just looks like works, because I don't understand how it is working:

select feeds.feed_id, feeds.title
from feeds
    left outer join channels on feeds.feed_id = channels.feed_id
    left outer join regions_channels on channels.channel_id = regions_channels.channel_id
    left outer join regions on regions_channels.region_id = regions.region_id
where regions._id is NULL
    or regions.selected = 1
group by feeds.feed_id
order by feeds.feed_id;

this doesn't feel right to me but it works so i am using it for now...

Was it helpful?

Solution

Your last AND was trimming regions table.

regions.selected=1 must be on WHEREclause.

If you choose NOT region.selected IS 0, then all feeds not disabled will show up.

Replaced GROUP BY with DISTINCT - IMO, it's more correct.

LEFT or LEFT OUTER is same in .

SELECT DISTINCT feeds.feed_id, feeds.title
FROM feeds
    LEFT JOIN channels ON feeds.feed_id = channels.feed_id
    LEFT JOIN regions_channels ON channels.channel_id = regions_channels.channel_id
    LEFT JOIN regions ON regions_channels.region_id = regions.region_id
WHERE NOT regions.selected IS 0
ORDER BY feeds.feed_id;

OTHER TIPS

By putting selected = 1 into the join condition, you have told the database to return either records that match that condition, or (because of OUTER), to return columns filled with NULL. You must put the condition into the WHERE clause so that it is checked after the join.

Second change: I've dropped the LEFT OUTER fropm the feeds/channels join because you did not say you wanted feeds that do not have channels.

SELECT feeds.feed_id, feeds.title
FROM feeds
JOIN channels ON feeds.feed_id = channels.feed_id
LEFT JOIN regions_channels ON channels.channel_id = regions_channels.channel_id
LEFT JOIN regions on regions_channels.region_id = regions.region_id
WHERE regions.selected = 1
   OR regions.selected IS NULL
GROUP BY feeds.feed_id
ORDER BY feeds.feed_id
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top