这个SQL怎么可能......
CREATE TABLE NewTable AS
SELECT A,B,C FROM Table1
minus
SELECT A, B, C From Table2
...在A列中创建一个包含NULL值的新表 当Table1或Table2在A列中都没有NULL值时?
但另一方面,这个SQL ......
SELECT * FROM
(
SELECT A,B,C FROM Table1
minus
SELECT A, B, C From Table2
)
WHERE A IS NULL
不返回任何行!
似乎不一致!
我认为这是Oracle中的一个错误。
当然,真正的SQL要复杂得多,但我相信这可以准确地说明问题的本质。
更新
这是ACTUAL SQL:
我执行了这个陈述:
CREATE TABLE MyMinus
AS
select
*
FROM
---begin main query
(
SELECT expenditure_item_date, expenditure_org, expenditure_type,
f_amount_billed, f_amount_billed_fc, f_amount_billed_us,
f_bl_creation_date, f_catalog_source, f_catalog_type, f_company,
f_company_code, f_cost_center_num, f_cuic, f_currency_code,
f_destination_type_code, f_distribution_id, f_distribution_num,
f_exchange_rate, f_extract_date, f_gl_account,
f_isms_jamis_project_num, f_line_id, f_local_use, f_location_num,
f_need_by_date, f_org_id, f_po_line_num, f_po_num, f_po_release_num,
f_project, f_project_num, f_promised_date, f_quantity_billed,
f_quantity_cancelled, f_quantity_delivered, f_quantity_ordered,
f_rel_approved_flag, f_rel_cancelled_flag, f_rel_cancel_date,
f_rel_closed_code, f_rel_hold_flag, f_rel_revision_num, f_task_num
FROM dw_mgr.po_distributions_curr_fct a
WHERE EXISTS (
SELECT 1
FROM dw_mgr.po_distributions_curr_fct b,
dw_mgr.po_lines_curr_fct,
dw_mgr.po_header_curr_fct
WHERE a.ROWID = b.ROWID
AND b.f_cuic = dw_mgr.po_lines_curr_fct.f_cuic
AND b.f_line_id = dw_mgr.po_lines_curr_fct.f_line_id
AND dw_mgr.po_lines_curr_fct.f_cuic =
dw_mgr.po_header_curr_fct.f_cuic
AND dw_mgr.po_lines_curr_fct.f_header_id =
dw_mgr.po_header_curr_fct.f_header_id
AND dw_mgr.po_header_curr_fct.f_header_creation_date <
ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'),
-48)
AND dw_mgr.po_header_curr_fct.f_po_status IN
('CLOSED', 'FINALLY CLOSED'))
MINUS
SELECT expenditure_item_date, expenditure_org, expenditure_type,
f_amount_billed, f_amount_billed_fc, f_amount_billed_us,
f_bl_creation_date, f_catalog_source, f_catalog_type, f_company,
f_company_code, f_cost_center_num, f_cuic, f_currency_code,
f_destination_type_code, f_distribution_id, f_distribution_num,
f_exchange_rate, f_extract_date, f_gl_account,
f_isms_jamis_project_num, f_line_id, f_local_use, f_location_num,
f_need_by_date, f_org_id, f_po_line_num, f_po_num, f_po_release_num,
f_project, f_project_num, f_promised_date, f_quantity_billed,
f_quantity_cancelled, f_quantity_delivered, f_quantity_ordered,
f_rel_approved_flag, f_rel_cancelled_flag, f_rel_cancel_date,
f_rel_closed_code, f_rel_hold_flag, f_rel_revision_num, f_task_num
FROM arch_fct.po_distributions_curr_fct a
WHERE EXISTS (
SELECT 1
FROM arch_fct.po_distributions_curr_fct b,
arch_fct.po_lines_curr_fct,
arch_fct.po_header_curr_fct
WHERE a.ROWID = b.ROWID
AND b.f_cuic = arch_fct.po_lines_curr_fct.f_cuic
AND b.f_line_id = arch_fct.po_lines_curr_fct.f_line_id
AND arch_fct.po_lines_curr_fct.f_cuic =
arch_fct.po_header_curr_fct.f_cuic
AND arch_fct.po_lines_curr_fct.f_header_id =
arch_fct.po_header_curr_fct.f_header_id
AND arch_fct.po_header_curr_fct.f_header_creation_date <
ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'),
-48)
AND arch_fct.po_header_curr_fct.f_po_status IN
('CLOSED', 'FINALLY CLOSED'))
)
然后这个。请注意,具有NULL值F_DISTRIBUTION_ID的行已插入到创建的表中。
SELECT COUNT(*) from MyMinus WHERE F_DISTRIBUTION_ID IS NULL
- 17行
然而,当我执行此操作时:
select
*
FROM
---begin main query
(
SELECT expenditure_item_date, expenditure_org, expenditure_type,
f_amount_billed, f_amount_billed_fc, f_amount_billed_us,
f_bl_creation_date, f_catalog_source, f_catalog_type, f_company,
f_company_code, f_cost_center_num, f_cuic, f_currency_code,
f_destination_type_code, f_distribution_id, f_distribution_num,
f_exchange_rate, f_extract_date, f_gl_account,
f_isms_jamis_project_num, f_line_id, f_local_use, f_location_num,
f_need_by_date, f_org_id, f_po_line_num, f_po_num, f_po_release_num,
f_project, f_project_num, f_promised_date, f_quantity_billed,
f_quantity_cancelled, f_quantity_delivered, f_quantity_ordered,
f_rel_approved_flag, f_rel_cancelled_flag, f_rel_cancel_date,
f_rel_closed_code, f_rel_hold_flag, f_rel_revision_num, f_task_num
FROM dw_mgr.po_distributions_curr_fct a
WHERE EXISTS (
SELECT 1
FROM dw_mgr.po_distributions_curr_fct b,
dw_mgr.po_lines_curr_fct,
dw_mgr.po_header_curr_fct
WHERE a.ROWID = b.ROWID
AND b.f_cuic = dw_mgr.po_lines_curr_fct.f_cuic
AND b.f_line_id = dw_mgr.po_lines_curr_fct.f_line_id
AND dw_mgr.po_lines_curr_fct.f_cuic =
dw_mgr.po_header_curr_fct.f_cuic
AND dw_mgr.po_lines_curr_fct.f_header_id =
dw_mgr.po_header_curr_fct.f_header_id
AND dw_mgr.po_header_curr_fct.f_header_creation_date <
ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'),
-48)
AND dw_mgr.po_header_curr_fct.f_po_status IN
('CLOSED', 'FINALLY CLOSED'))
MINUS
SELECT expenditure_item_date, expenditure_org, expenditure_type,
f_amount_billed, f_amount_billed_fc, f_amount_billed_us,
f_bl_creation_date, f_catalog_source, f_catalog_type, f_company,
f_company_code, f_cost_center_num, f_cuic, f_currency_code,
f_destination_type_code, f_distribution_id, f_distribution_num,
f_exchange_rate, f_extract_date, f_gl_account,
f_isms_jamis_project_num, f_line_id, f_local_use, f_location_num,
f_need_by_date, f_org_id, f_po_line_num, f_po_num, f_po_release_num,
f_project, f_project_num, f_promised_date, f_quantity_billed,
f_quantity_cancelled, f_quantity_delivered, f_quantity_ordered,
f_rel_approved_flag, f_rel_cancelled_flag, f_rel_cancel_date,
f_rel_closed_code, f_rel_hold_flag, f_rel_revision_num, f_task_num
FROM arch_fct.po_distributions_curr_fct a
WHERE EXISTS (
SELECT 1
FROM arch_fct.po_distributions_curr_fct b,
arch_fct.po_lines_curr_fct,
arch_fct.po_header_curr_fct
WHERE a.ROWID = b.ROWID
AND b.f_cuic = arch_fct.po_lines_curr_fct.f_cuic
AND b.f_line_id = arch_fct.po_lines_curr_fct.f_line_id
AND arch_fct.po_lines_curr_fct.f_cuic =
arch_fct.po_header_curr_fct.f_cuic
AND arch_fct.po_lines_curr_fct.f_header_id =
arch_fct.po_header_curr_fct.f_header_id
AND arch_fct.po_header_curr_fct.f_header_creation_date <
ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'),
-48)
AND arch_fct.po_header_curr_fct.f_po_status IN
('CLOSED', 'FINALLY CLOSED'))
)
WHERE
f_distribution_id is null
我得到0行。
为什么将记录插入临时表似乎会引入具有NULL DIST ID的行?
这个由自定义数据归档程序动态生成的减去查询的SQL会尝试验证应该在DW_MGR模式中归档的数据实际上是否已复制到ARCH_FCT(存档)模式。它返回的差异包括17条记录,其中MyMinus临时表中的F_DISTRIBUTION_ID与源DW_MG.PO_DISTRIBUTIONS_CURR_FCT表中的F_DISTRIBUTION_ID不匹配,因为它们是NULL。因此,存档过程是在发现差异时进行设计的。问题是为什么存在差异,即当NULL值不在SOURCE PO_DISTRIBUTIONS_CURR_FCT表中时,NULL值如何进入MyMinus表?
编辑:
拥有Oracle META访问权限的人可以发布以下Oracle错误的信息。我被提到了他们,但我签约合同找到了我的合作伙伴,他可以告诉我我们的支持ID#是什么。我最终会发现,但很快就会知道。如果您不想发布它,请将以下错误引用视为我的问题的潜在相关信息:
Bug 8209309: MINUS IS SHOWING DIFFERENCES WITH CTAS + INSERT
Bug 7834950: WRONG RESULTS WITH MINUS OPERATOR
答案 0 :(得分:4)
退出你的排骨。这是一个Oracle错误。我会向你证明:
首先,它必须是第一个返回NULLS for DISTRIBUTION ID的SQL,所以要隔离该SQL并将其称为“SQL1”。
好的,让我们为了讨论而简化SQL1并说它是这种格式:
CREATE TABLE TempTable AS
SELECT
F_DISTRIBUTION_ID,
FIELD2,
FIELD3,...FIELD99
FROM WHATEVER
WHERE WHATEVER
然后,您发现在执行此操作时,您将找到具有NULL DIST ID的行:
SELECT COUNT(*) FROM TempTable WHERE F_DISTRIBUTION_ID IS NULL
--Some positive number of rows returned.
如果Oracle不是废话,您可以更改所选字段的数量,以便只选择F_DISTRIBUTION_ID,当您计算NULL值为F_DISTRIBUTION_ID的行数时,您会得到相同的结果,对吧?对!但事实并非如此,因为甲骨文是一种不可靠的恐龙。
试试这个:
CREATE TABLE TempTable AS
SELECT
F_DISTRIBUTION_ID
FROM WHATEVER
WHERE WHATEVER
SELECT COUNT(*) FROM TempTable WHERE F_DISTRIBUTION_ID IS NULL
我给甜甜圈打钱,你得到0行。
现在,请调用Microsoft并告诉他们您要升级到SQL Server 2008 R2。
答案 1 :(得分:2)
首先,我将摆脱ROWID加入ROWID。 然后我会让表格变得独一无二(不要在MINUS上方的查询和MINUS下面的查询中重复使用'a'和'b'。)
最后,我会查看这17行并尝试在“dw_mgr.po_distributions_curr_fct”中找到匹配的记录,并使用DUMP(F_DISTRIBUTION_ID)查看列值的奇怪之处。
答案 2 :(得分:1)
一般不应该。
唯一可能的情况是,如果你有一些高级安全功能(细粒度访问控制),优化器可以看到A在table1 / table2中不能为空,所以返回零行,但FGAC开始阻止你通过返回null来查看列中的实际值。
EDIT。 “使用[虚拟专用数据库]列屏蔽行为,所有行都会显示,甚至是那些引用敏感列的行。但是,敏感列显示为NULL值。”
http://download.oracle.com/docs/cd/E11882_01/network.112/e10574/vpd.htm#i1014682
答案 3 :(得分:1)
当我插入MyMinus时,我认为F_DISTRIBUTION_ID可能为NULL的唯一方法是,如果它以某种方式返回NULL,就在第一个查询中。
重现这个(在9i和10g上):
SQL> INSERT INTO table1 VALUES (NULL, 2, 3);
1 row created.
SQL> INSERT INTO table2 VALUES (1, 2, 3);
1 row created.
SQL> SELECT *
2 FROM (
3 SELECT a, b, c FROM table1
4 MINUS
5 SELECT a, b, c FROM table2);
A B C
---------- ---------- ----------
2 3
但是,关于查询在自己运行时不返回任何行...这是其他的东西。一个错误不会让我感到惊讶......但你试过取出那些EXISTS吗?当然,有许多不同的方法,但也许所有这些子查询都会在内存中引起一些有趣的事情。
例如:
SELECT expenditure_item_date, expenditure_org, expenditure_type,
f_amount_billed, f_amount_billed_fc, f_amount_billed_us,
f_bl_creation_date, f_catalog_source, f_catalog_type, f_company,
f_company_code, f_cost_center_num, f_cuic, f_currency_code,
f_destination_type_code, f_distribution_id, f_distribution_num,
f_exchange_rate, f_extract_date, f_gl_account,
f_isms_jamis_project_num, f_line_id, f_local_use, f_location_num,
f_need_by_date, f_org_id, f_po_line_num, f_po_num, f_po_release_num,
f_project, f_project_num, f_promised_date, f_quantity_billed,
f_quantity_cancelled, f_quantity_delivered, f_quantity_ordered,
f_rel_approved_flag, f_rel_cancelled_flag, f_rel_cancel_date,
f_rel_closed_code, f_rel_hold_flag, f_rel_revision_num, f_task_num
FROM dw_mgr.po_distributions_curr_fct a
dw_mgr.po_lines_curr_fct,
dw_mgr.po_header_curr_fct
WHERE a.f_cuic = dw_mgr.po_lines_curr_fct.f_cuic
AND a.f_line_id = dw_mgr.po_lines_curr_fct.f_line_id
AND dw_mgr.po_lines_curr_fct.f_cuic = dw_mgr.po_header_curr_fct.f_cuic
AND dw_mgr.po_lines_curr_fct.f_header_id = dw_mgr.po_header_curr_fct.f_header_id
AND dw_mgr.po_header_curr_fct.f_header_creation_date < ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'), -48)
AND dw_mgr.po_header_curr_fct.f_po_status IN ('CLOSED', 'FINALLY CLOSED')
MINUS
SELECT expenditure_item_date, expenditure_org, expenditure_type,
f_amount_billed, f_amount_billed_fc, f_amount_billed_us,
f_bl_creation_date, f_catalog_source, f_catalog_type, f_company,
f_company_code, f_cost_center_num, f_cuic, f_currency_code,
f_destination_type_code, f_distribution_id, f_distribution_num,
f_exchange_rate, f_extract_date, f_gl_account,
f_isms_jamis_project_num, f_line_id, f_local_use, f_location_num,
f_need_by_date, f_org_id, f_po_line_num, f_po_num, f_po_release_num,
f_project, f_project_num, f_promised_date, f_quantity_billed,
f_quantity_cancelled, f_quantity_delivered, f_quantity_ordered,
f_rel_approved_flag, f_rel_cancelled_flag, f_rel_cancel_date,
f_rel_closed_code, f_rel_hold_flag, f_rel_revision_num, f_task_num
FROM arch_fct.po_distributions_curr_fct a,
arch_fct.po_lines_curr_fct,
arch_fct.po_header_curr_fct
WHERE a.f_cuic = arch_fct.po_lines_curr_fct.f_cuic
AND a.f_line_id = arch_fct.po_lines_curr_fct.f_line_id
AND arch_fct.po_lines_curr_fct.f_cuic = arch_fct.po_header_curr_fct.f_cuic
AND arch_fct.po_lines_curr_fct.f_header_id = arch_fct.po_header_curr_fct.f_header_id
AND arch_fct.po_header_curr_fct.f_header_creation_date < ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'), -48)
AND arch_fct.po_header_curr_fct.f_po_status IN ('CLOSED', 'FINALLY CLOSED')
答案 4 :(得分:1)
我有一个可能相关的问题,当使用一堆复杂的视图并存在时,它开始是MINUS的一个问题。我把它缩小到一个可能的优化问题 - 你可以通过使用像“upper(F_DISTRIBUTION_ID)IS NULL”这样的东西来阻止优化器基于“F_DISTRIBUTION_ID IS NULL”搞乱事情来解决它。
在这些情况下,几乎不可能为错误报告创建一个简化的测试用例 - 它可能只发生在非常特定的场景中(它不像MINUS毕竟会被完全打破)。根据我的问题,我根本无法减少查询,并且仍然会发生。
仅供参考我的问题是一个查询,它基本上将一堆东西加入到源表中,称之为Employee。我在Employee的主键上有一个where子句 - 如果我做了一个EmployeeId = foo的地方,它将返回一个额外的行,其中的空值不应该是(内部连接的表中的列) - 如果我这样做的话a upper(EmployeeId)= foo然后我会得到正确的结果。显然,EmployeeId值来自与谓词匹配的所有行中的相同单元格 - 所以它显然是一个错误。
答案 5 :(得分:0)
我刚遇到同样的错误。并构建一个if else条件来获取这些值:D
表1
A ! B
null 35
'if else'条件:P
select
Case
WHEN a."Add" >= '0' THEN to_number(a."Add" - b."Cease" )
ELSE (b."Cease")*-1
End as "X"
from table 1
答案
-35