SQL查询:获取列A和列B值不存在的行
很抱歉,标题很混乱,但没有找到更好的标题。情况如下:SQL查询:获取列A和列B值不存在的行,sql,oracle,Sql,Oracle,很抱歉,标题很混乱,但没有找到更好的标题。情况如下: CREATE TABLE orders ( order_id int NOT NULL, company_id int NOT NULL, last_update date NULL ) 表数据: ORDER_ID COMPANY_ID LAST_UPDATE 1 1 2020/06/08 2
CREATE TABLE orders (
order_id int NOT NULL,
company_id int NOT NULL,
last_update date NULL
)
表数据:
ORDER_ID COMPANY_ID LAST_UPDATE
1 1 2020/06/08
2 1 2020/06/08
3 1 2020/06/08
4 2 2020/06/08
5 2 2020/01/27
6 3 2020/06/08
7 3 2020/06/08
8 3 2020/06/08
9 3 NULL
10 4 2020/06/08
11 4 2020/06/08
12 4 2020/06/08
13 4 2020/06/08
14 4 2020/06/08
我想要所有的行,有一个公司,其中没有同一个公司的行,并且最后的更新时间超过3个月或为空
什么不起作用:
我不能使用带有日期的简单WHERE子句,因为这只会过滤掉第5行和第9行。我只想要第1-3行和第10-14行
有效的方法是放慢速度:
我可以在SELECT DISTINCT company_ID[…]中使用子查询和company_ID,但这会完全破坏我的性能。在prod环境中,我有将近50M行,子查询的结果集太大了 我当前的解决方法: 我只是按公司id、上次更新和Java代码中的continue排序结果,如果上次更新太旧了。但这也不是最优的 问题: 要实现这一点,是否有性能SQL的唯一方法。也许是一组。。。有-从句
提前谢谢 您可以使用窗口功能:
select o.*
from (select o.*, min(last_update) over (partition by company_id) as min_last_update
from orders o
) o
where min_last_update >= add_months(sysdate, -3);
但一个简单的不存在也可以:
select o.*
from orders o
where not exists (select 1
from orders o2
where o2.company_id = o.company_id and
o2.last_update < add_months(sysdate, -3)
);
其中任何一个都可以利用orderscompany\u id上的索引,即上次更新。您可以使用窗口功能:
select o.*
from (select o.*, min(last_update) over (partition by company_id) as min_last_update
from orders o
) o
where min_last_update >= add_months(sysdate, -3);
但一个简单的不存在也可以:
select o.*
from orders o
where not exists (select 1
from orders o2
where o2.company_id = o.company_id and
o2.last_update < add_months(sysdate, -3)
);
这两种方法中的任何一种都可以利用orderscompany\u id,last\u update上的索引。您可以按如下方式使用窗口功能:
SELECT T.* FROM (
SELECT T.*,
MIN(CASE WHEN LAST_UPDATE IS NULL THEN LAST_UPDATE - 100
ELSE LAST_UPDATE END) OVER(
PARTITION BY T.COMPANY_ID
) AS MIN_LAST_UPDATE
FROM ORDERS T ) T
WHERE T.MIN_LAST_UPDATE >= ADD_MONTHS(SYSDATE, - 3);
您可以按如下方式使用窗口功能:
SELECT T.* FROM (
SELECT T.*,
MIN(CASE WHEN LAST_UPDATE IS NULL THEN LAST_UPDATE - 100
ELSE LAST_UPDATE END) OVER(
PARTITION BY T.COMPANY_ID
) AS MIN_LAST_UPDATE
FROM ORDERS T ) T
WHERE T.MIN_LAST_UPDATE >= ADD_MONTHS(SYSDATE, - 3);
我可以在SELECT DISTINCT company_ID[…]中使用子查询和company_ID,但这会完全破坏我的性能-听起来好像缺少索引。此表中定义了哪些索引,您当前的索引碎片级别是什么?这个表在质量上经历了什么类型的搅动?缺少索引是一个问题,但在我的例子中,最好的tipp正在从不存在变为不存在。我不知道SELECT1语法。使用此选项比使用SELECT DISTINCT company_id要好得多,因为这会导致一百万个id,这使得NOT IN检查非常昂贵。我可以在SELECT DISTINCT company_id[…]中使用子查询和company_id,但这会完全破坏我的性能-听起来好像缺少索引。此表中定义了哪些索引,您当前的索引碎片级别是什么?这个表在质量上经历了什么类型的搅动?缺少索引是一个问题,但在我的例子中,最好的tipp正在从不存在变为不存在。我不知道SELECT1语法。使用这个比使用选择不同的公司id要好得多,因为这会导致一百万个id,这使得不在检查非常昂贵!从不存在切换到不存在给了我巨大的性能提升。thx!从“不存在”切换到“不存在”给了我巨大的性能提升。