通过多个分组连接多个表
Join multiple tables by multiple grouping
我们有一个传球控制系统,每个传球动作都存储在 Event
table 中 MSSQL Server
。我们想根据下图所示的关系将多个 table 与 Event
table 连接起来。但是,我不确定我使用的分组方法是否正确,因为查询需要花费很多时间。能否请您解释一下哦,如何通过多个分组加入这些 table?这是我使用的 JOIN
子句:
SELECT t.CardNo, t.EventTime, t1.EmployeeName,
t1.Status, t2.EventCH, t3.DoorName, t4.JobName, t5.DeptName
FROM Event t
LEFT JOIN Employee AS t1 ON t.EmployeeID = t1.ID
LEFT JOIN EventType AS t2 ON t.EventTypeID = t2.ID
LEFT JOIN Door AS t3 ON t.DoorID = t3.ID
LEFT JOIN Job AS t4 ON t1.JobID = t4.ID
LEFT JOIN Department AS t5 ON t1.DepartmentID = t5.ID
ORDER BY t.EventID Desc
更新: 下面发布执行计划:
嘿,你试过创建两个 CTE 来对连接进行分组吗?
所以在一个 CTE 中为员工、部门和工作创建一个连接。
对于另一个 CTE,为 Event、Eventtype 和 Door 创建一个连接。最后,使用 Employee ID 和 ID 加入两个 CTE。
将联接的 table 聚合在一起可能比一次完成联接更快。顺便说一下,每个 table 的唯一约束如何?
;WITH a AS
(
SELECT
t1.ID
,t1.EmployeeName
,t1.Status
,t4.JobName
,t5.DeptName
FROM
Employee t1
LEFT JOIN Job t4
ON t1.JobID = t4.ID
LEFT JOIN Department t5
ON t1.DepartmentID = t5.ID
)
,b AS
(
SELECT
t.EmployeeID
,t.CardNo
,t.EventTime
,t2.EventCH
,t3.DoorName
FROM
[Event] t
LEFT JOIN EventType t2
ON t.EventTypeID = t2.ID
LEFT JOIN Door t3
ON t.DoorID = t3.ID
)
SELECT
*
FROM
b
LEFT JOIN a
ON b.EmployeeID = a.ID
您问题中的查询不代表查询计划中的查询。特别是,它有条件
RIGHT(t.cardno, 8) = RIGHT(t1.cardno, 8)
函数的使用排除了计划索引的使用。
我的建议是为每个 table 添加一个虚拟列,对其进行索引,然后在连接中使用它:
alter table tEvent add cardno8 as RIGHT(cardno, 8);
alter table tEmployee add cardno8 as RIGHT(cardno, 8);
create index idx_tEvent_cardno8 tEvent(cardno8);
create index idx_tEmployee_cardno8 tEmployee(cardno8);
如果将比较更改为:
,这应该有助于提高性能
on t.cardno8 = t1.cardno8
此外,您的查询没有 WHERE
子句,因此它(大概)正在处理大量数据。
我们有一个传球控制系统,每个传球动作都存储在 Event
table 中 MSSQL Server
。我们想根据下图所示的关系将多个 table 与 Event
table 连接起来。但是,我不确定我使用的分组方法是否正确,因为查询需要花费很多时间。能否请您解释一下哦,如何通过多个分组加入这些 table?这是我使用的 JOIN
子句:
SELECT t.CardNo, t.EventTime, t1.EmployeeName,
t1.Status, t2.EventCH, t3.DoorName, t4.JobName, t5.DeptName
FROM Event t
LEFT JOIN Employee AS t1 ON t.EmployeeID = t1.ID
LEFT JOIN EventType AS t2 ON t.EventTypeID = t2.ID
LEFT JOIN Door AS t3 ON t.DoorID = t3.ID
LEFT JOIN Job AS t4 ON t1.JobID = t4.ID
LEFT JOIN Department AS t5 ON t1.DepartmentID = t5.ID
ORDER BY t.EventID Desc
更新: 下面发布执行计划:
嘿,你试过创建两个 CTE 来对连接进行分组吗?
所以在一个 CTE 中为员工、部门和工作创建一个连接。 对于另一个 CTE,为 Event、Eventtype 和 Door 创建一个连接。最后,使用 Employee ID 和 ID 加入两个 CTE。
将联接的 table 聚合在一起可能比一次完成联接更快。顺便说一下,每个 table 的唯一约束如何?
;WITH a AS
(
SELECT
t1.ID
,t1.EmployeeName
,t1.Status
,t4.JobName
,t5.DeptName
FROM
Employee t1
LEFT JOIN Job t4
ON t1.JobID = t4.ID
LEFT JOIN Department t5
ON t1.DepartmentID = t5.ID
)
,b AS
(
SELECT
t.EmployeeID
,t.CardNo
,t.EventTime
,t2.EventCH
,t3.DoorName
FROM
[Event] t
LEFT JOIN EventType t2
ON t.EventTypeID = t2.ID
LEFT JOIN Door t3
ON t.DoorID = t3.ID
)
SELECT
*
FROM
b
LEFT JOIN a
ON b.EmployeeID = a.ID
您问题中的查询不代表查询计划中的查询。特别是,它有条件
RIGHT(t.cardno, 8) = RIGHT(t1.cardno, 8)
函数的使用排除了计划索引的使用。
我的建议是为每个 table 添加一个虚拟列,对其进行索引,然后在连接中使用它:
alter table tEvent add cardno8 as RIGHT(cardno, 8);
alter table tEmployee add cardno8 as RIGHT(cardno, 8);
create index idx_tEvent_cardno8 tEvent(cardno8);
create index idx_tEmployee_cardno8 tEmployee(cardno8);
如果将比较更改为:
,这应该有助于提高性能on t.cardno8 = t1.cardno8
此外,您的查询没有 WHERE
子句,因此它(大概)正在处理大量数据。