不使用相交运算符重写 SQL 查询
Rewriting an SQL Query Without Using Intersect Operator
我要查询这条语句:
Bars that are frequented by both Mike and John
[table 常客由 2 列组成:饮酒者和他们去的酒吧]
我最初想使用这个 SQL 查询,使用相交运算符:
SELECT bar
FROM frequents
WHERE drinker ='Mike'
INTERSECT
SELECT bar
FROM frequents
WHERE drinker ='John'
但 MySQL 不支持使用相交运算符。我虽然可能会使用 Join 运算符,但我很难重写此查询。
这是你想要的inner join
:
SELECT a.bar
FROM frequents a
JOIN frequents b ON a.bar = b.bar
WHERE a.drinker = 'Mike'
AND b.drinker = 'John';
请注意,交集比较 select 列表中的所有列,因此等效连接需要执行相同的操作。在你的情况下,它只是一列。
intersect
运算符并没有真正直接转换为 inner join
,因为 intersect
returns 行对于比较的集合是常见的,而连接过滤器在给定条件下生成一组新的行,这些行由连接集中的行组成。 null
值的处理方式(和重复值)也存在差异。
另一种选择是将 exists
谓词与相关子查询一起使用:
SELECT a.bar
FROM frequents a
WHERE a.drinker ='Mike'
AND EXISTS (
SELECT 1 FROM frequents b
WHERE a.bar = b.bar
AND b.drinker ='John'
);
或 in
谓词:
SELECT bar
FROM frequents
WHERE drinker ='Mike'
AND bar IN (SELECT bar FROM frequents WHERE drinker ='John')
还有许多其他方法可以做到这一点,但我想我会在这里停下来:)
一个简单的方法是使用聚合:
select f.bar
from frequents f
group by f.bar
having max(drinker = 'John') > 0 and
max(drinker = 'Mike) > 0;
或者:
select f.bar
from frequents f
where f.drinker in ('John', 'Mike')
group by f.bar
having count(*) = 2;
我喜欢 having
子句,因为我发现它对各种情况都很灵活,例如 John 和 Mike,但 Sara 则不然。或者 John、Mike、Sara 和 Abigail 中的三个。
我要查询这条语句:
Bars that are frequented by both Mike and John
[table 常客由 2 列组成:饮酒者和他们去的酒吧]
我最初想使用这个 SQL 查询,使用相交运算符:
SELECT bar
FROM frequents
WHERE drinker ='Mike'
INTERSECT
SELECT bar
FROM frequents
WHERE drinker ='John'
但 MySQL 不支持使用相交运算符。我虽然可能会使用 Join 运算符,但我很难重写此查询。
这是你想要的inner join
:
SELECT a.bar
FROM frequents a
JOIN frequents b ON a.bar = b.bar
WHERE a.drinker = 'Mike'
AND b.drinker = 'John';
请注意,交集比较 select 列表中的所有列,因此等效连接需要执行相同的操作。在你的情况下,它只是一列。
intersect
运算符并没有真正直接转换为 inner join
,因为 intersect
returns 行对于比较的集合是常见的,而连接过滤器在给定条件下生成一组新的行,这些行由连接集中的行组成。 null
值的处理方式(和重复值)也存在差异。
另一种选择是将 exists
谓词与相关子查询一起使用:
SELECT a.bar
FROM frequents a
WHERE a.drinker ='Mike'
AND EXISTS (
SELECT 1 FROM frequents b
WHERE a.bar = b.bar
AND b.drinker ='John'
);
或 in
谓词:
SELECT bar
FROM frequents
WHERE drinker ='Mike'
AND bar IN (SELECT bar FROM frequents WHERE drinker ='John')
还有许多其他方法可以做到这一点,但我想我会在这里停下来:)
一个简单的方法是使用聚合:
select f.bar
from frequents f
group by f.bar
having max(drinker = 'John') > 0 and
max(drinker = 'Mike) > 0;
或者:
select f.bar
from frequents f
where f.drinker in ('John', 'Mike')
group by f.bar
having count(*) = 2;
我喜欢 having
子句,因为我发现它对各种情况都很灵活,例如 John 和 Mike,但 Sara 则不然。或者 John、Mike、Sara 和 Abigail 中的三个。