1

我想获取 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
4

2 回答 2

1

两者在功能上是等效的,除非代码为 NULL。SQL 是一种描述性语言,而不是一种过程语言。语法描述了结果集,而不是(必然)如何完成处理。

这里有多种方法可以编写这样的查询(包括一个not in版本)。查询的执行方式取决于引擎选择的路径。 这里有一些选项。如果你用谷歌搜索,有更多关于不同查询公式的具体性能时间的例子。

第二种结构不是编写外连接查询的好方法。这是首选语法:

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
于 2013-01-16T11:22:54.217 回答
1

它们是不同的,但正如 Gordon Linoff 所展示的,当转换为 ASNSI 连接语法时,更容易理解为什么。在这种形式下,您的第二个查询变为:

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为空,这也会失败,因为您不能=用来比较空值)。因此,外连接永远找不到匹配项,不妨省略,因此您将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

... then 外连接条件可以找到匹配项。如果找不到匹配项,则在WHERE评估子句时,A.flh_id_messaggio现在确实会是null,所以这就像您原来的NOT EXISTS.

还有一个假设是 MON_MONITORAGGIO_ID 是唯一的,很可能就是这种情况。但是由于您仅在没有匹配项时才计数,因此我认为您不需要DISTINCT.

于 2013-01-16T12:39:34.593 回答