我们说我有这两种关系:
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响应。
答案 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;