我有这三个表:
广告活动
id | name | campaign_strategy_id
----+-------------+----------------------
5 | Teste Diego | 3
campaign_strategy_blocked_routes
campaign_strategy_id | route_id
----------------------+----------
3 | 2
3 | 6
路线:
name | id
-----------------+----
Vonex Teste | 3
Filial Total IP | 2
Filial TotalIP | 6
Tellfree teste | 5
我需要查看未在广告系列中屏蔽的路线。在这种情况下,请注意,广告系列ID 5有两个被阻止的路线:2和6,但我需要在我的选择中显示其他两条路线:3和5.
我有这样的事情:
select campaigns.name, routes.id as route_id from campaigns left join campaign_strategy_blocked_routes on campaigns.campaign_strategy_id = campaign_strategy_blocked_routes.campaign_strategy_id left join routes on campaign_strategy_blocked_routes.route_id = routes.id
但结果显然是:
name | route_id
-------------+----------
Teste Diego | 2
Teste Diego | 6
而且,就像我说的,我需要的是:
name | route_id
-------------+----------
Teste Diego | 3
Teste Diego | 5
是否可以这样做?
答案 0 :(得分:2)
select c.name, r.id
from campaigns c
inner join routes r
on not exists(select 1 from campaign_strategy_blocked_routes
where route_id = r.id
and campaign_strategy_id = c.campaign_strategy_id)
<强>解释强>
如果子查询没有找到campaigns
表中的任何匹配行,则routes
表和campaign_strategy_blocked_routes
表的行将被连接。
exists
中的一个或多个匹配行, true
会返回campaign_strategy_blocked_routes
,但由于我们关心的是没有匹配的情况,我们会否定表达式(即{{1} }})。
子查询基本上等同于
not exists(...)
因此它会找到广告系列的封锁路线
但是,不是在子查询中连接表,而是由外部查询提供值select 1
from campaigns c
inner join campaign_strategy_blocked_routes csbr
on csbr.campaign_strategy_id = c.campaign_strategy_id
inner join routes r on csbr.route_id = r.id
和r.id
作为常量。
使用c.campaign_strategy_id
因为我们不关心从子查询返回任何特定数据,我们只想知道是否有任何行要返回。
答案 1 :(得分:0)
试试这个:
SELECT a.name, c.id AS route_id from campaigns a, campaign_strategy_blocked_routes b
FULL OUTER JOIN routes c
ON b.route_id = c.id
WHERE b.route_id is null
OR c.id is null
返回:
name route_id
Teste Diego 3
Teste Diego 5
答案 2 :(得分:0)
这个问题相当棘手,需要棘手的解决方案。这样的事情。
--tables
declare @campaigns table(id int, name varchar(20), campaign_strategy_id int)
insert @campaigns values ( 5, 'Teste Diego', 3),
( 6, 'Test 2', 4) --I added an extra test row
declare @campaign_strategy_blocked_routes table(id int,route_id int)
insert @campaign_strategy_blocked_routes values(3,2),(3,6),
(4,3) --extra test
declare @routes table(name varchar(10),id int)
insert @routes values ('a',3), ('a',2), ('a',6), ('a',5) --names are not used
select distinct c.name,t.route_id
from @campaigns c
left join @campaign_strategy_blocked_routes x1 on c.campaign_strategy_id=x1.id
--here is the trick. non-existing rows
--cross apply -- MS SQL Server
left join lateral --PostgreSQL
(select id
from @routes r --all routes
except
--used routes
select route_id
from @campaign_strategy_blocked_routes x
where x.id=x1.id
) t(route_id)
on true -- PostgreSQL only
order by c.name
--Results
name route_id
Test 2 2
Test 2 5
Test 2 6
Teste Diego 3
Teste Diego 5