【发布时间】:2016-03-01 14:09:53
【问题描述】:
如下图所示,我通过连接多个表来检索数据。另一方面,由于 Event 表的 FK 列 (EmployeeID) 中没有数据,我必须使用 CardNo (nvarchar) 字段来连接两个表。另一方面,Event 和 Employee 表中 CardNo 字段的位数不同,我还必须使用 SQL Server 的 RIGHT 函数,这使得查询的执行时间大约延长了 10 倍。那么,在这个场景中我该怎么办呢?我可以使用 CardNo 字段而不将其数据类型更改为 int 等(因为更改后可能会出现其他问题,最好在不更改其数据类型的情况下找到解决方案)。这也是下面查询的执行计划。
查询:
; WITH a AS (SELECT emp.EmployeeName, emp.Status, dep.DeptName, job.JobName, emp.CardNo
FROM TEmployee emp
LEFT JOIN TDeptA AS dep ON emp.DeptAID = dep.DeptID
LEFT JOIN TJob AS job ON emp.JobID = job.JobID),
b AS (SELECT eve.EventID, eve.EventTime, eve.CardNo, evt.EventCH, dor.DoorName
FROM TEvent eve LEFT JOIN TEventType AS evt ON eve.EventType = evt.EventID
LEFT JOIN TDoor AS dor ON eve.DoorID = dor.DoorID)
SELECT * FROM b LEFT JOIN a ON RIGHT(a.CardNo, 8) = RIGHT(b.CardNo, 8)
ORDER BY b.EventID ASC
【问题讨论】:
-
为什么是 MySQL 标签? (那是另一种产品……)
-
您可以将
RIGHT()的内容存储在数据库中,而不是每次都即时计算。由于您没有提供任何数据,我真的不知道这会是什么样子 -
这里的问题不在于要连接的数据是 varchar,而是您要连接其中的一部分,这需要您将列包装在一个函数中。这会使查询变为 nonSARGable,并且它必须为强制索引扫描的每一行计算正确的 8 个字符。
-
@JoePhilllips 感谢您的回复。您是指带有数据的 CardNo 吗?如果是这样,这里的示例数据为 00014293720、00007004720、00013145687、00012597006。如果您需要其他数据或表格结果,请告诉我。
-
解决问题的绝对最佳方法是停止将多条信息存储在单个值中。当您只需要加入某个值的一部分时,几乎总是会出现这种情况。第二个最佳选择是@JoePhilllips 已经建议的,将这部分信息放在计算列中。
标签: sql sql-server sql-server-2008 join indexing