如果所有值都等于某个值,则SQL查询仅获取行

时间:2014-06-17 12:06:42

标签: sql postgresql

我们说我有这两种关系:

alert

id    http_code_result  domain_id   ip_src

1          404              1         1.1.1.1
2          404              1         1.1.1.1
3          200              1         1.1.1.1

domain

id    name
1     google

我想只获得404回复的域名。因此,对于IP地址1.1.1.1,它将返回0行,因为id为1的域也有一个HTTP 200响应。

7 个答案:

答案 0 :(得分:1)

我对您的问题的理解是:“您想要检索具有HTTP响应404的域。如果同一域的响应不是404(说200),则不应显示该域名。< /强>“

基于这种理解,我们可以编写如下查询::

SELECT d.id, d.name
FROM domain d, alert a
WHERE a.domain_id=d.id AND a.domain_id NOT IN(SELECT domain_id
                                              FROM alert
                                              WHERE http_code_result!=404);

请参阅此 SQLFiddle 链接以便更好地理解

答案 1 :(得分:0)

使用左连接获取404警报并在WHERE子句中使用IS NULL,以免考虑具有404警报的域。

SELECT domain.*
FROM domain LEFT JOIN alert ON domain_id = domain.id AND http_code_result = 404
WHERE alert.id IS NULL;

答案 2 :(得分:0)

我希望查询的正面和负面EXISTS半连接最快,特别是如果两种情况都有多行。

SELECT *
FROM   domain d
WHERE  EXISTS (
   SELECT 1
   FROM   alert
   WHERE  domain_id = d.id 
   AND    http_code_result = 404
   )
AND NOT EXISTS (
   SELECT 1
   FROM   alert
   WHERE  domain_id = d.id 
   AND    http_code_result <> 404
   );

关于确切条件,您的问题并不完全清楚 alert (id, http_code_result)上的多列索引应该是性能的完美。

甚至是嵌套变体:

SELECT *
FROM   domain d
WHERE  EXISTS (
   SELECT 1
   FROM   alert
   WHERE  domain_id = d.id 
   AND    http_code_result = 404
   AND    NOT EXISTS (
      SELECT 1
      FROM   alert
      WHERE  domain_id = d.id 
      AND    http_code_result <> 404
      )
   )

首先应用更具选择性的过滤器。

答案 3 :(得分:0)

我对这个问题并不是100%肯定,但是当我说对了,你可以通过使用聚合来解决这个问题:

SELECT
    domain.name,
    alert.ip_src
FROM    alert
    INNER JOIN domain ON alert.domain_id = domain.id
GROUP BY    -- create a group by name and ip:
    domain.name,
    alert.ip_src
HAVING  array_agg(http_code_result) @> ARRAY[404]   -- this group must have a 404
AND NOT array_agg(http_code_result) @> ARRAY[200];  -- this group may not have a 200

也许你不想要ip地址,而不仅仅是把它留下来。

答案 4 :(得分:0)

select d.name from domain d, alert a where a.domain_id=d.id and domain_id not in(select domain_id from alert where http_code_result!=404);

此查询将获取所有包含404以外响应代码的域,然后将其从主数据中排除。

答案 5 :(得分:0)

select name
from
    domain d
    inner join (
        select domain_id
        from alert
        group by domain_id
        having not bool_or(http_code_result <> 404)
    ) a on d.domain_id = a.id

使用not bool_or代替下面明显的bool_and,因为它只需要找到一个真正的行。聚合是在加入表演之前完成的,尽管在这种情况下实际上可能没有区别。

select domain_id
from alert
group by domain_id
having bool_and(http_code_result = 404)

答案 6 :(得分:-1)

尝试类似:

select domain_id, 
       count(http_code_result = 404 or null) as count_404, 
       count(http_code_result != 404 or null) as count_not_404
from alert a
where ip_src = '1.1.1.1'
group by domain_id
having count_404 > 0 and count_not_404 = 0;