当 FK 字段为 NULL 时使用索引连接两个表

Using Index for joining two tables when FK field is NULL

我们开始维护一个使用 SQL 服务器的新项目,在某些 table 中存在一些关于数据的问题,如下所述。有 2 个 table 称为 EmployeePassPass table 保持每个 Employee 的进出。

员工

|| ID       || Name       || CardNo ||
======================================
|| 1        || John       || 101    ||
|| 2        || Christof   || 102    ||
|| 3        || Jurgen     || 103    ||
|| 4        || Jose       || 104    ||
|| 5        || Mary       || 105    ||

通过

|| ID       || EmployeeID || CardNo ||
======================================
|| 1        || NULL       || 101    ||
|| 2        || NULL       || 105    ||
|| 3        || NULL       || 103    ||
|| 4        || NULL       || 101    ||
|| 5        || NULL       || 102    ||
|| 6        || NULL       || 104    ||
|| 7        || NULL       || 104    ||
|| 8        || NULL       || 103    ||
|| 9        || NULL       || 105    ||
|| 10       || NULL       || 101    ||

另一方面,由于 Pass table 的 EmployeeID 列对于每次传递都是空的,我们必须使用 CardNo 列才能加入两个 table。

但是使用如下所示的JOIN子句会导致查询执行的时间更长,我认为可能有更好的方法通过使用索引等代替PK来优化查询。我们已尝试创建索引,但无法为 CardNo 列创建索引。

您能否向我们说明如何解决该问题?谢谢...

SELECT *  
FROM Pass p
LEFT JOIN Employee e ON RIGHT(e.CardNo, 8) = RIGHT(p.CardNo, 8) --I have to trim card no as the digit sizes are different

更新: 我尝试应用以下脚本,但只有这部分有效:

alter table Pass add cardno8 as RIGHT(CardNo, 8);
alter table Employee add cardno8 as RIGHT(CardNo, 8);

这部分报错:"Column 'cardno8' in table 'Pass' is of a type that is invalid for use as a key column in an index."

create index idx_tEvent_cardno8 ON Pass(cardno8);
create index idx_tEmployee_cardno8 ON Employee (cardno8);

有什么想法吗?

如果问题出在查询的性能上,那么您只需要 Employee(CardNo):

上的索引
create index idx_employee_cardno on employee(cardno);

如果您只对其他一两个列(例如name或id)感兴趣,可以将它们添加到cardno之后的索引中。

我能想到的(除了权限之外)解释索引创建失败的唯一原因是 cardno 类型错误。引用 documentation:

Columns that are of the large object (LOB) data types ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, or image cannot be specified as key columns for an index.

鉴于示例数据,这似乎不太可能。如果这是一个问题,请将类型更改为更合适的类型(或出于相同目的使用计算列)。

此外,您的查询应在所有地方使用限定的列名(否则会出现错误):

SELECT *
FROM Pass p LEFT JOIN
     Employee e
     ON e.CardNo = p.CardNo;
--------^