考虑两个表:
Foo:
id INT,
name VARCHAR
Bar:
id INT,
foo_id INT REFERENCES Foo(id),
event_type VARCHAR DEFAULT NULL,
event_duration INT DEFAULT NULL
每个Foo项目可以有多个Bar事件。 如何查询没有满足以下任一条件的任何Bar事件的Foo项目:
event_type
不是以下值之一:'miss','scratch','scrape' event_duration
非空例如,考虑:
Foo id=1:
event_type: hit | event_duration: NULL
event_type: poke | event_duration: NULL
event_type: capture | event_duration: NULL
Foo id=2:
event_type: hit | event_duration: 2
event_type: poke | event_duration: NULL
event_type: capture | event_duration: NULL
Foo id=3:
event_type: miss | event_duration: NULL
event_type: poke | event_duration: NULL
event_type: capture | event_duration: NULL
Foo id=4:
event_type: strike | event_duration: NULL
event_type: hit | event_duration: NULL
event_type: land | event_duration: NULL
只应返回包含id=1
和id=4
的Foo项目。不应返回带有id=2
的项目,因为event_duration
之一不是NULL。不应返回包含id=3
的项目,因为event_type
之一是miss
(位于禁止的event_types列表中)。
我尝试过来自this terrific answer的各种想法,这些想法对我希望从中构建此查询所能学到的情况的概括作出回应。唉,我一直无法将答案概括到足以解决这个问题。这是一个非工作查询的例子,还有其他一些失败的尝试:
SELECT
f.name
FROM
Foo f JOIN Bar b ON f.id = b.foo_id
GROUP BY
b.event_type, b.event_duration
HAVING
b.event_type not in ('miss', 'scratch', 'scrape')
AND
b.event_duration not null
这是另一个不工作的查询:
SELECT
f.name
FROM
(
SELECT
f.name, b.event_duration
FROM
Foo f JOIN Bar b ON f.id = b.foo_id
GROUP BY
b.event_type
HAVING
b.event_type not in ('miss', 'scratch', 'scrape')
)
GROUP BY
b.event_duration
HAVING
b.event_duration not null
还有很多关于JOIN和子查询的其他未处理查询。 请注意,Foo
表有近500万行,Bar
表有近200万行。这些表在相关字段上编制索引,但在这些大表上根本不可能O(n^2)
。
答案 0 :(得分:0)
您可以使用NOT EXISTS
来获得所需的结果。
SELECT f.name
FROM foo f
WHERE NOT EXISTS (SELECT 1 FROM bar b
WHERE b.foo_id = f.id
AND (b.event_type IN ('miss','scratch','scrape')
OR b.event_duration IS NOT NULL)
)
答案 1 :(得分:0)
试试这个,即使听起来很简单,我认为你的情况也可以。
select f1.id, f1.name from
Foo f1
left join
(
select distinct f.id
from Foo f
join Bar b on f.id = b.foo_id
where
( b.event_type IN ('miss','scratch','scrape') ) OR ( b.event_duration IS NOT NULL )
) f2 on f1.id = f2.id
WHERE
(f2.id is null)
答案 2 :(得分:0)
您可以在Foo表中创建一个“计数器缓存”字段,该字段仅保存关联的条形图项的计数。
我认为通过两个查询可以更快地解决您的问题:
查询以更新所有Foo项的计数器缓存。因为这只会看索引列,所以它应该相当快。
第二个查询不会进行任何连接,但只会查询Foo表中所需的条件,并将“计数器缓存”值设为0.
通过智能管理“计数器缓存”列,您可能只需运行第一个查询一次。 (当然,你的程序必须保持“计数器缓存”列同步)。
答案 3 :(得分:0)
我会试试这个
SELECT DISTINCT f.Id
FROM Foo f
WHERE NOT EXIST (
SELECT DISTINCT b.foo_id
WHERE b.foo_id = f.Id
AND (b.event_type IN ('miss','scratch','scrape')
OR b.event_duration IS NOT NULL)
)
你也可以像这样使用Merge:
WHEN NOT MATCHED
查找结果