2012-02-28 44 views
0

这是我有:SQL - 如何查询具有相反关系的相关对象的COUNT(0)的所有对象?

Person 
    name = varchar 

Helmet 
    person = foreignkey -> Person 
    is_safe = boolean 

现在,批作业,我需要查询(无ORM,只是原始SQL)对于具有0 Helmet是安全的所有Person。我显然可以循环遍历数据库中的每个Person等,但我需要在一个查询中执行此操作,并一次将其限制为100(数据库中有这些吸盘的novemdecillions),并删除每个Person。我不需要在结果中附加每个记录的Helmet记录。我只需要Person记录(自然删除将会级联),但我不能简单地发出DELETE来代替我的SELECT,因为在删除它们之前我需要在其他地方执行其他操作。

我使用Postgres的,但我宁愿使用一个查询,或多或少DB无关,如果可能的话。

这里就是我抽象地想出:

SELECT * FROM person 
    WHERE (SELECT COUNT(*) FROM helmet 
     WHERE person_id = person.id AND is_safe = false) = 0 
    LIMIT 100 

这显然不是有效的SQL,但我希望有一个相同的功能,但有效的版本。

回答

0

我最终使用:

SELECT * 
FROM person p 
WHERE NOT EXISTS 
    (
     SELECT h.person_id 
     FROM helmet h 
     WHERE h.person_id = p.id 
      AND is_safe = true 
    ) 
LIMIT 100 

果然停止扫描表一旦找到匹配的100个结果。

0
SELECT person.* 
FROM person 
LEFT JOIN (SELECT DISTINCT person_id FROM helmet) AS T2 ON person.id = T2.person_id 
WHERE T2.person_id IS NULL 
LIMIT 100 
3
select * 
from person 
where person_id not in 
    (
    select person_id 
    from helmet 
    where is_safe = false 
    ) 
2
SELECT * 
FROM (
    SELECT p.* 
    FROM Person p 
    INNER JOIN Helmet h ON p.id = h.person 
    GROUP BY p.id 
    HAVING SUM(h.is_safe) = 0 
) inner_select 
LIMIT 100 

因此,该查询由两个部分组成:

  1. 查询的主力是内部查询。该查询将每个人与他的所有头盔结合在一起。然后它使用GROUP BY两个关联一个特定人员的所有行。一旦我们有了一个组,我们就可以在每个组上使用聚合函数,在这种情况下,我们使用SUM来计算安全头盔的数量。 HAVING条款使用SUM仅用于选择安全头盔总数(即安全头盔数量)等于零的组。
  2. 外部查询确保将LIMIT应用于内部查询的结果,而不是计算精确结果所需的表的行。
+0

非常感谢。你能解释一下它是如何工作的(特别是其他的包装器'SELECT')? – orokusaki 2012-02-28 19:03:24

+0

非常感谢Patrik – orokusaki 2012-02-28 19:12:40

+0

不客气! – PatrikAkerstrand 2012-02-28 19:16:48

相关问题