当 FK 字段为 NULL 时使用索引连接两个表
Using Index for joining two tables when FK field is NULL
我们开始维护一个使用 SQL 服务器的新项目,在某些 table 中存在一些关于数据的问题,如下所述。有 2 个 table 称为 Employee
和 Pass
,Pass
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;
--------^
我们开始维护一个使用 SQL 服务器的新项目,在某些 table 中存在一些关于数据的问题,如下所述。有 2 个 table 称为 Employee
和 Pass
,Pass
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
, orimage
cannot be specified as key columns for an index.
鉴于示例数据,这似乎不太可能。如果这是一个问题,请将类型更改为更合适的类型(或出于相同目的使用计算列)。
此外,您的查询应在所有地方使用限定的列名(否则会出现错误):
SELECT *
FROM Pass p LEFT JOIN
Employee e
ON e.CardNo = p.CardNo;
--------^