在连接表中计算的最佳方式

时间:2017-06-23 11:05:01

标签: sql sql-server database

所以我有一些数据库实体描述了所述项目中的项目和用户:

enter image description here 然后我编写了一个查询以获取项目集合,以及一个额外的字段来获取项目中的用户数量:

select x.RefProject, x.ProjectName, x.DateCreated, x.PlannedDueDate, 
(select count(RefUser) from ProjectUsers where RefProject = x.RefProject) as ProjectUserCount
from Projects x
left outer join ProjectUsers a on x.RefProject = a.RefProject
where a.RefUser = 1

我的问题是 - 有更好的方法来计算用户数吗?我觉得像CTE表或功能将是更正确的"这样做的方法。

2 个答案:

答案 0 :(得分:2)

首先,您的where子句将外连接转换为内连接。所以你可能也是明确的。然后使用窗口函数:

select p.RefProject, p.ProjectName, p.DateCreated, p.PlannedDueDate, 
       count(*) over (partition by p.RefProject) as ProjectUserCount
from Projects p join
     ProjectUsers pu
     on p.RefProject = pu.RefProject
where pu.RefUser = 1;

编辑:

我发现过滤器可能会限制实际数量。更准确的表示使用子查询:

select p.*
from (select p.RefProject, p.ProjectName, p.DateCreated, p.PlannedDueDate, 
             count(*) over (partition by p.RefProject) as ProjectUserCount,
             pu.RefUser
      from Projects p join
           ProjectUsers pu
           on p.RefProject = pu.RefProject
     ) p
where RefUser = 1;

答案 1 :(得分:2)

替代方法是编写一个按RefProject分组的子查询,完成总和,然后加入你的表。

SELECT x.RefProject, x.ProjectName, x.DateCreated, x.PlannedDueDate, T.Cnt
FROM Projects AS x
LEFT JOIN (   SELECT RefProject, COUNT(RefUser) AS Cnt
              FROM ProjectUser
              GROUP BY RefProject) AS T
    ON T.RefProject = x.RefProject
LEFT JOIN ProjectUsers AS a
    ON x.RefProject = a.RefProject
WHERE a.RefUser = 1;

使用标量函数或多语句表值函数会降低性能,这个和你的查询都很好,只需很好地索引表,这样就可以了。

或者,如果分组成为问题,您可以创建索引视图并与其连接。这会增加一些写入开销,但会对读取性能产生奇迹。

CREATE VIEW RefProjectCountView
WITH SCHEMABINDING
AS
SELECT RefProject, COUNT_BIG(RefUser) AS Cnt
FROM ProjectUser
GROUP BY RefProject;
GO

CREATE UNIQUE CLUSTERED INDEX PK_RefProjectCountView
ON RefProjectCountView (RefProject);
GO

SELECT x.RefProject, x.ProjectName, x.DateCreated, x.PlannedDueDate, T.Cnt
FROM Projects AS x
LEFT JOIN RefProjectCountView AS T WITH(NOEXPAND)
    ON T.RefProject = x.RefProject
LEFT JOIN ProjectUsers AS a
    ON x.RefProject = a.RefProject
WHERE a.RefUser = 1;
SQL Server需要

WITH(NOEXPAND)提示来查询视图索引,而不是扩展完整的select语句。