结合连接并存在于连接表中

时间:2017-06-15 09:09:02

标签: mysql join not-exists

我无法解决这个SQL难题,我差不多想出来但最后一部分有点挑战。

我有一个广告系列表和一个用户表

广告系列的状态为:有效/无效。

最重要的是,广告系列和用户之间有一个联接表:campaign_users。此表用于专门为一部分用户分配广告系列。

鉴于此数据:

Campaigns
id  name        status
1   campaign_a  active
2   campaign_b  active
3   campaign_c  active
4   campaign_d  inactive

Users
id  name
1   user_a
2   user_b
3   user_c

Campaign_users
id  campaign_id     user_id
1   2               1
2   3               2
3   4               1

我想制作一个结合了几个“方面”的查询。正如我所说,我在最后一部分停留在这里是我的步骤:

第1步:选择有效的广告系列:

SELECT campaigns.* 
FROM campaigns 
WHERE campaigns.status = 'active'

output
campaign: 1,2,3

第2步:(和)并非专门分配给任何人:

SELECT campaigns.* 
FROM campaigns 
WHERE campaigns.status = 'active'
WHERE NOT EXISTS(select * FROM campaign_users WHERE campaign_users.campaign_id = campaigns.id)

output:
campaign: 1

第3步:(和)专门分配给passed_in user_id(1)。

SELECT campaigns.* 
FROM campaigns 
WHERE campaigns.status = 'active' 
INNER JOIN campaign_users ON campaign_users.campaign_id = campaigns.id 
AND campaign_users.user_id = 1

output:
campaign: 2

最后一步:

这是我被卡住的部分。

查询将所有“方面”组合在一起:只有非独占的活动广告系列(不分配给任何人)并且对于传入的user_id是独占的。

写这个感觉有点像矛盾,但内部联接只返回连接表中存在的广告系列,但它会跳过“非独占”广告系列。

expected output:

with passed_in user_id of 1

campaign: 1,2 (Active & non exclusive and exclusively assigned to user 2)

with passed_in user_id of 2

campaign: 1,3 (Active & non exclusive and exclusively assigned to user 2)

with passed_in user_id of 3

campaign: 3 (Active & non exclusive but no exclusive assigned to user 3)

2 个答案:

答案 0 :(得分:1)

You can use a simple trick: outer join all campaign_users to the campaigns. You'll get a row per campaign and user for exclusive campaigns and a row with user null for non-exclusive campaigns. Keep all campaigns for either the user in question (say user 1) or all users (user null).

select c.*
from campaigns c
left join campaign_users cu on cu.campaign_id = c.id
where c. status = 'active' and (cu.user_id = 1 or cu.user_id is null);

答案 1 :(得分:0)

You can UNION the queries for Step 2 and 3 to get the required result, e.g.:

SELECT campaign_id
FROM campaigns 
WHERE campaigns.status = 'active'
WHERE NOT EXISTS(select * FROM campaign_users WHERE campaign_users.campaign_id = campaigns.id)

UNION 

SELECT campaign_id
FROM campaigns 
WHERE campaigns.status = 'active' 
INNER JOIN campaign_users ON campaign_users.campaign_id = campaigns.id 
AND campaign_users.user_id = ?