合并连接并存在于连接 table
Combine join and exists on join table
我一直在解决这个 sql 难题,我几乎想通了,但最后一部分有点挑战性。
我有一个活动 table 和一个用户 table
活动的状态为:有效/无效。
最重要的是,活动和用户之间存在连接 table:campaign_users。此 table 用于专门将活动分配给一部分用户。
鉴于此数据:
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
我想进行一个结合几个 'facets' 的查询。正如我所说,我卡在了最后一部分,这是我的步骤:
第 1 步:Select 个活动活动:
SELECT campaigns.*
FROM campaigns
WHERE campaigns.status = 'active'
output
campaign: 1,2,3
第2步:(and)不独占分配给任何人:
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步:(and)独占分配给passed_inuser_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
最后一步:
这是我卡住的部分。
将所有 'facets' 组合在一起的查询:仅不排他(分配给任何人)并且不排他传入 user_id 的活动活动。
写这个感觉有点自相矛盾,但内部联接仅存在于联接 table 中的 returns 个活动,但它跳过了 'non exclusive' 个活动。
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)
您可以UNION
第 2 步和第 3 步的查询以获得所需的结果,例如:
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 = ?
您可以使用一个简单的技巧:将所有 campaign_users
外连接到 campaigns
。对于独家广告系列,您将获得针对每个广告系列和用户的一行,对于非独家广告系列,您将获得一行用户为空的行。为相关用户(比如用户 1)或所有用户(用户 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);
我一直在解决这个 sql 难题,我几乎想通了,但最后一部分有点挑战性。
我有一个活动 table 和一个用户 table
活动的状态为:有效/无效。
最重要的是,活动和用户之间存在连接 table:campaign_users。此 table 用于专门将活动分配给一部分用户。
鉴于此数据:
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
我想进行一个结合几个 'facets' 的查询。正如我所说,我卡在了最后一部分,这是我的步骤:
第 1 步:Select 个活动活动:
SELECT campaigns.*
FROM campaigns
WHERE campaigns.status = 'active'
output
campaign: 1,2,3
第2步:(and)不独占分配给任何人:
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步:(and)独占分配给passed_inuser_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
最后一步:
这是我卡住的部分。
将所有 'facets' 组合在一起的查询:仅不排他(分配给任何人)并且不排他传入 user_id 的活动活动。
写这个感觉有点自相矛盾,但内部联接仅存在于联接 table 中的 returns 个活动,但它跳过了 'non exclusive' 个活动。
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)
您可以UNION
第 2 步和第 3 步的查询以获得所需的结果,例如:
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 = ?
您可以使用一个简单的技巧:将所有 campaign_users
外连接到 campaigns
。对于独家广告系列,您将获得针对每个广告系列和用户的一行,对于非独家广告系列,您将获得一行用户为空的行。为相关用户(比如用户 1)或所有用户(用户 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);