Sam*_*Sam 6 sql oracle oracle12c
我遇到了EXISTS子句无法正常运行的查询。该查询甚至返回不存在匹配记录的项目的结果,似乎完全忽略了EXISTS。它过去工作正常,我认为从Oracle 12.1升级到12.2后,麻烦就开始了。
以下是完整的查询(仅更改了表和列的名称以使它们更易读,但我保留了所有逻辑以防与之相关):
WITH FirstDateFilter AS (
SELECT ReferenceDate,
Type,
LAG(Type, 1, 0) OVER (ORDER BY ReferenceDate) AS PreviousType
FROM ReferenceDateTable
WHERE ItemId = :itemId
AND ReferenceDate <= :endDate
AND Type IN (:type1, :type2)
), SecondDateFilter AS (
SELECT ReferenceDate
FROM FirstDateFilter
WHERE ReferenceDate >= :startDate
AND ReferenceDate >= ( SELECT StartDate FROM StartDateTable WHERE ItemId = :itemId )
AND Type = :type1
AND PreviousType = :type1
)
SELECT ReferenceDate, Value
FROM ResultTable
WHERE ItemId = :itemId
AND EXISTS ( SELECT * FROM SecondDateFilter WHERE SecondDateFilter.ReferenceDate = ResultTable.ReferenceDate )
Run Code Online (Sandbox Code Playgroud)
在处理了一些测试数据之后,我认为导致失败的(部分?)行是AND ReferenceDate >= ( SELECT StartDate FROM StartDateTable WHERE ItemId = :itemId )第二个WITH中的子查询。
我发现以下任何编辑都会导致EXISTS再次按预期工作:
( SELECT ReferenceDate FROM SecondDateFilter WHERE SecondDateFilter.ReferenceDate = ResultTable.ReferenceDate )在SELECT ... FROM ResultTable最后一个解决方案实际上解决了该查询的问题(技术上不一样,但是底层的业务逻辑检查出结果始终是相同的),但是我想知道EXISTS子句是否存在一般性问题(可能只是我应该知道在Oracle 12.2中?我还有很多查询可以利用它。
下面是一个重复该错误的测试脚本。下面的查询按预期返回2行,但是删除注释行将得到5行。
CREATE TABLE ReferenceDateTable
(
ItemId number,
ReferenceDate date,
Type varchar2(1)
);
INSERT INTO ReferenceDateTable (ItemId, ReferenceDate, Type) VALUES (1, to_date('19000201', 'YYYYMMDD'), '1');
INSERT INTO ReferenceDateTable (ItemId, ReferenceDate, Type) VALUES (1, to_date('19000202', 'YYYYMMDD'), '1');
INSERT INTO ReferenceDateTable (ItemId, ReferenceDate, Type) VALUES (1, to_date('19000203', 'YYYYMMDD'), '2');
INSERT INTO ReferenceDateTable (ItemId, ReferenceDate, Type) VALUES (1, to_date('19000204', 'YYYYMMDD'), '1');
INSERT INTO ReferenceDateTable (ItemId, ReferenceDate, Type) VALUES (1, to_date('19000205', 'YYYYMMDD'), '1');
CREATE TABLE ResultTable
(
ItemId number,
ReferenceDate date,
Value number
);
INSERT INTO ResultTable (ItemId, ReferenceDate, Value) VALUES (1, to_date('19000201', 'YYYYMMDD'), 1);
INSERT INTO ResultTable (ItemId, ReferenceDate, Value) VALUES (1, to_date('19000202', 'YYYYMMDD'), 2);
INSERT INTO ResultTable (ItemId, ReferenceDate, Value) VALUES (1, to_date('19000203', 'YYYYMMDD'), 3);
INSERT INTO ResultTable (ItemId, ReferenceDate, Value) VALUES (1, to_date('19000204', 'YYYYMMDD'), 4);
INSERT INTO ResultTable (ItemId, ReferenceDate, Value) VALUES (1, to_date('19000205', 'YYYYMMDD'), 5);
CREATE TABLE StartDateTable
(
ItemId number,
StartDate date
);
INSERT INTO StartDateTable (ItemId, StartDate) VALUES (1, to_date('19000101', 'YYYYMMDD'));
WITH FirstDateFilter AS (
SELECT ReferenceDate,
Type,
LAG(Type, 1, 0) OVER (ORDER BY ReferenceDate) AS PreviousType
FROM ReferenceDateTable
WHERE ItemId = 1
AND ReferenceDate <= to_date('19000205', 'YYYYMMDD')
AND Type IN ('1', '2')
), SecondDateFilter AS (
SELECT ReferenceDate
FROM FirstDateFilter
WHERE ReferenceDate >= to_date('19000201', 'YYYYMMDD')
--AND ReferenceDate >= ( SELECT StartDate FROM StartDateTable WHERE ItemId = 1 )
AND Type = '1'
AND PreviousType = '1'
)
SELECT ReferenceDate, Value
FROM ResultTable
WHERE ItemId = 1
AND EXISTS ( SELECT * FROM SecondDateFilter WHERE SecondDateFilter.ReferenceDate = ResultTable.ReferenceDate )
;
Run Code Online (Sandbox Code Playgroud)
根据Jonathan 在 Twitter 上的评论,建议的解决方法是使用unnest外部存在子查询中的提示,因为该问题是由于错误(可能是错误 28319114)引起的。
[...]
SELECT ReferenceDate, Value
FROM ResultTable
WHERE ItemId = 1
AND EXISTS ( SELECT /*+ UNNEST */ * FROM SecondDateFilter WHERE SecondDateFilter.ReferenceDate = ResultTable.ReferenceDate )
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
118 次 |
| 最近记录: |