我想拍摄ENI_MONITOR的每一个记录,这是一个孤儿。在ENI_FLUSSI_HUB中,相应的记录不应存在。这两种配方都是正确的吗?左外连接如何思考?
SELECT /*+ PARALLEL (mon, 10) */
COUNT(1)
FROM B
WHERE B.mon_flag_ann = 'N'
AND NOT EXISTS
(
SELECT /*+ PARALLEL (c, 10) */
1
FROM A
WHERE B.MON_ID_MESSAGGIO = A.flh_id_messaggio
AND B.MON_COD_TP_PROCESSO = A.flh_tipo_processo_cod
AND A.FLH_FLAG_ANN = 'N'
);
SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM B,
A
WHERE B.mon_flag_ann = 'N'
AND B.MON_ID_MESSAGGIO = A.flh_id_messaggio(+)
AND B.MON_COD_TP_PROCESSO = A.flh_tipo_processo_cod(+)
AND A.FLH_FLAG_ANN(+) = 'N'
AND A.flh_id_messaggio(+) IS NULL
答案 0 :(得分:1)
这两个在功能上是等价的,除非在代码为NULL的情况下。 SQL是描述性语言,而不是过程语言。语法描述结果集,而不是(必然)描述处理的完成方式。
这里有多种方法来编写这样的查询(包括not in
版本)。查询的执行方式取决于引擎选择的路径。 Here是一些选择。如果您使用Google,则会针对查询的不同配方提供更多具体效果时间示例。
第二种结构不是编写外连接查询的好方法。以下是首选语法:
SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM B left outer join
A
on B.MON_ID_MESSAGGIO = A.flh_id_messaggio and
B.MON_COD_TP_PROCESSO = A.flh_tipo_processo_cod and
A.FLH_FLAG_ANN = 'N'
WHERE B.mon_flag_ann = 'N' and
A.flh_id_messaggio IS NULL
答案 1 :(得分:1)
它们是不同的,但更容易理解为什么在转换为ASNSI连接语法时,正如Gordon Linoff所示。在该表格中,您的第二个查询将变为:
SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM B
LEFT JOIN A
ON A.flh_id_messaggio = B.MON_ID_MESSAGGIO
AND A.flh_tipo_processo_cod = B.MON_COD_TP_PROCESSO
AND A.FLH_FLAG_ANN = 'N'
AND A.flh_id_messaggio IS NULL
WHERE B.mon_flag_ann = 'N'
外部联接条件包括A.flh_id_messaggio = B.MON_ID_MESSAGGIO
和 A.flh_id_messaggio IS NULL
,这两者都不是真的。 (即使B.MON_ID_MESSAGGIO
为null,这也会失败,因为您无法使用=
来比较空值。因此,外部联接永远不会找到匹配项,也可能会被省略,因此您将从MON_MONITORAGGIO_ID
计算所有不同的B
值。
但是,如果您将IS NULL
检查结果移至WHERE
子句(正如Gordon所做的那样):
SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM B
LEFT JOIN A
ON A.flh_id_messaggio = B.MON_ID_MESSAGGIO
AND A.flh_tipo_processo_cod = B.MON_COD_TP_PROCESSO
AND A.FLH_FLAG_ANN = 'N'
WHERE B.mon_flag_ann = 'N'
AND A.flh_id_messaggio IS NULL
...然后外部连接条件可以找到匹配项。如果找不到匹配项,则在评估WHERE
子句时,A.flh_id_messaggio
现在确实为null
,因此这就像您原来的NOT EXISTS
。
还假设MON_MONITORAGGIO_ID是唯一的,很可能就是这种情况。但由于你只计算没有匹配的时候,我认为你不需要DISTINCT
。