如何解决我该如何为自引用SELECT编写SQL,该自引用SELECT的某些字段与同一字段不同,而另一些条件不相同?
我有以下(简化的)表:
CREATE TABLE IF NOT EXISTS `resource` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,`host` TEXT NOT NULL,`inspecting` INTEGER DEFAULT 0,`visitedAt` TEXT
);
可以有多个记录,它们具有相同的host
值和/或一个被视为host
的子域的值。例如:
id | host | inspecting | visitedAt
---------------------------------------------------------
1 | example.com | 0 | null
2 | example.com | 0 | 2020-09-28 00:00:00
3 | sub.example.com | 1 | null
4 | example.org | 0 | null
因此,这些主机可能已被访问或当前可以被检查。我想找到最旧的主机,该主机最近没有被访问过并且当前未被检查,并且该主机也不被认为是最近访问或当前被检查的主机的子域。
因此,假设example.com
当前正在检查中或最近被访问过,那么我不想匹配example.com
或sub.example.com
。在以上数据示例中,example.org
应该匹配。
我已经用JOIN
和WHERE (NOT) EXISTS
尝试了各种查询,但是我无法使其正常工作。
最接近的查询类似(虽然可能不准确):
SELECT `self`.*
FROM `resource` AS `self`
WHERE
`self`.`inspecting` != 1 AND
(`self`.`visitedAt` IS NULL OR datetime( `self`.`visitedAt` ) <= datetime( 'now','-10 minutes' )) AND
NOT EXISTS (
SELECT 1
FROM
`resource` AS `probe`
WHERE
`probe`.`inspecting` = 1 AND
(`self`.`host` = `probe`.`host` OR `self`.`host` LIKE "%." || `probe`.`host`) AND
(`probe`.`visitedAt` IS NOT NULL AND datetime( `probe`.`visitedAt` ) > datetime( 'now','-10 minutes' ))
)
ORDER BY `self`.`visitedAt` ASC
LIMIT 1
是否可以通过单个查询过滤出这样的行?
解决方法
您可以在选择中使用带有子查询的公用表表达式来创建条件列,如下所示:
context['form2'] = self.second_form_class(instance=request.Sitiocontratado.sitioproyecto)
现在结果应如下所示:
WITH `t` AS (
SELECT
-- Create a conditional column `inspectionFlag`
CASE WHEN
(
-- Checks the `resource` table for hosts that has inspecting = 1
SELECT 1 FROM `resource` AS `probe`
WHERE (`probe`.`host` LIKE '%.' || `self`.`host` OR `self`.`host` LIKE '%.' || `probe`.`host` OR `self`.`host` = `probe`.`host`)
AND `probe`.`inspecting` = 1
) IS NOT NULL THEN 1 ELSE 0 END
AS `inspectionFlag`,CASE
WHEN
-- Checks the `resource` table for hosts that are being visited
(SELECT 1 FROM `resource` AS `probe`
WHERE (`probe`.`host` LIKE '%.' || `self`.`host` OR `self`.`host` LIKE '%.' || `probe`.`host` OR `self`.`host` = `probe`.`host`)
AND `probe`.`visitedAt` IS NOT NULL
AND datetime( `probe`.`visitedAt` ) > datetime( 'now','-10 minutes' )
) IS NOT NULL THEN 1 ELSE 0 END
AS `visitedFlag`,`self`.*
FROM `resource` AS `self`
)
SELECT `t`.* FROM `t`
现在只需要使用新的“标志”列来过滤出主机,就像这样:
| inspectionFlag | visitedFlag | id | host | inspecting | visitedAt |
| -------------- | ----------- | --- | --------------- | ---------- | ------------------- |
| 1 | 1 | 1 | example.com | 0 | |
| 1 | 1 | 2 | example.com | 0 | 2020-09-28 08:00:00 |
| 1 | 1 | 3 | sub.example.com | 1 | |
| 0 | 0 | 4 | example.org | 0 | |
结果:
WITH `t` AS (
SELECT
CASE WHEN
(
SELECT 1 FROM `resource` AS `probe`
WHERE (`probe`.`host` LIKE '%.' || `self`.`host` OR `self`.`host` LIKE '%.' || `probe`.`host` OR `self`.`host` = `probe`.`host`)
AND `probe`.`inspecting` = 1
) IS NOT NULL THEN 1 ELSE 0 END
AS `inspectionFlag`,CASE
WHEN
(SELECT 1 FROM `resource` AS `probe`
WHERE (`probe`.`host` LIKE '%.' || `self`.`host` OR `self`.`host` LIKE '%.' || `probe`.`host` OR `self`.`host` = `probe`.`host`)
AND `probe`.`visitedAt` IS NOT NULL
AND datetime( `probe`.`visitedAt` ) > datetime( 'now',`self`.*
FROM `resource` AS `self`
)
SELECT `t`.* FROM `t`
WHERE `t`.`inspectionFlag` = 0 AND `t`.`visitedFlag` = 0
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。