在可能为 NULL 的列上完全连接两个表时的 SQL 索引

问题描述 投票:0回答:1

我有两个表

table1
table2
,都有列
group
element_id1
element_id2
date
。 对于每个
date
和每个
group
,该组中有多个元素。每个元素都有 2 个 id(每个
element_id1
都映射到一个
element_id2
,反之亦然,但有时其中一个可以是
NULL
[存在但未记录在我们的该行表中])。 我想找到每个
group
date
在一个表中但不在另一个表中的元素。为了检查两个元素是否相等,我将它们匹配到
element_id1
element_id2
(取决于哪一个是非
NULL
)。 例如,让表格为:

  • 表1:
元素_id1 元素_id2 日期
G1 1 2024 年 1 月 31 日
G1 2 B 2024 年 1 月 31 日
G1 3 C 2024 年 1 月 31 日
G1 A 2024 年 2 月 2 日
G1 4 D 2024 年 2 月 2 日
G2 1 A 2024 年 1 月 31 日
G2 5 2024 年 2 月 2 日
  • 表2:
元素_id1 元素_id2 日期
G1 1 A 2024 年 1 月 31 日
G1 B 2024 年 1 月 31 日
G1 A 2024 年 2 月 2 日
G1 4 2024 年 2 月 2 日
G2 1 A 2024 年 1 月 31 日
G2 F 2024 年 2 月 2 日

我想要的结果是

元素_id1 元素_id2 日期 状态
G1 3 C 2024 年 1 月 31 日 表 2 中缺失
G2 5 2024 年 2 月 2 日 表 2 中缺失
G2 F 2024 年 2 月 2 日 表 1 中缺失

我想在表中设置INDEX。这里有哪些好的指数?我应该对 (

group
,
date
,
element_id1
,
element_id2
) 的组合建立索引吗?但问题有时是
elemet_id
之一是
NULL
。我可以只对两个表中的组和日期建立索引吗?

我使用的SQL如下,但是非常慢:

SELECT COALESCE(t1.group, t2.group) as [Group],
       COALESCE(t1.element_id1, t2.element_id1) as element_id1,
       COALESCE(t1.element_id2, t2.element_id2) as element_id2,
       COALESCE(t1.[date], t2.[date]) as [date],
       CASE WHEN t1.[date] IS NULL THEN 'Missing from table1'
            ELSE 'Missing from table2'
       END AS [Status]
FROM
       table1 t1
FULL JOIN
       table2 t2
ON     t1.[group] = t2.[group]
       AND t1.[date] = t2.[date]
       AND (t1.element_id1 = t2.element_id1 OR t1.element_id2 = t2.element_id2)
WHERE t1.[date] IS NULL OR t2.[date] IS NULL
sql indexing non-clustered-index full-join
1个回答
0
投票

OR 条件将成为限制。

对此的优化可以是拆分查询并将所有结果合并,或者反转逻辑并使用 AND 而不是 OR。

例如;

SELECT
  *, 'Missing from T2'
FROM
  T1
WHERE
  NOT EXISTS (
    SELECT *
      FROM T2
     WHERE T2.group       = T1.group
       AND T2.[date]      = T1.[date]
       AND T2.element_id1 = T1.element_id1
  )
  AND NOT EXISTS (
    SELECT *
      FROM T2
     WHERE T2.group       = T1.group
       AND T2.[date]      = T1.[date]
       AND T2.element_id2 = T1.element_id2
  )

UNION ALL

SELECT
  *, 'Missing from T1'
FROM
  T2
WHERE
  NOT EXISTS (
    SELECT *
      FROM T1
     WHERE T1.group       = T2.group
       AND T1.[date]      = T2.[date]
       AND T1.element_id1 = T2.element_id1
  )
  AND NOT EXISTS (
    SELECT *
      FROM T1
     WHERE T1.group       = T2.group
       AND T1.[date]      = T2.[date]
       AND T1.element_id2 = T2.element_id2
  )

那么两个表应该各有两个索引:

  • (group, [date], element_id1)
  • (group, [date], element_id2)

这是大量的代码重复,但这也是一个不寻常的表设置和要求。

© www.soinside.com 2019 - 2024. All rights reserved.