繁体   English   中英

如何在T-SQL视图中重用子查询

[英]How to reuse subquery in T-SQL View

我正在尝试优化一个SQL视图。 这里的关系是一对多的,一个项目有很多任务:

create view [schema].[vName]
    select p.ProjectId as 'ProjectId'
            -- ...
            -- excluded some selected columns and subqueries where this comment is
            -- ...

            , (select count(t.TaskId)
               from Task t with (nolock)
               where t.PrimarySearchEntityId = p.ProjectId and t.IsDeleted = 0) as 'Total_Tasks'
            , (select count(t.TaskId)
               from Task t with (nolock)
               where t.PrimarySearchEntityId = p.ProjectId and isnull(t.taskowner, 'Unassigned') <> 'Unassigned' and t.IsDeleted = 0) as 'Assigned_Tasks'
            , (select count(t.TaskId)
               from Task t with (nolock)
               where t.PrimarySearchEntityId = p.ProjectId and t.TaskStatusId in (400, 500) and
                   t.IsDeleted = 0) as 'Completed_Tasks'
            , (select count(t.TaskId)
               from Task t with (nolock)
               where t.PrimarySearchEntityId = p.ProjectId and t.TaskStatusId not in (400, 500) and
                   t.IsDeleted = 0) as 'Remaining_Tasks'
            , (select count(t.TaskId)
               from Task t with (nolock)
               where t.PrimarySearchEntityId = p.ProjectId and t.DueDate < getutcdate() and t.TaskStatusId not in (400, 500) and t.IsDeleted = 0) as 'Late_Tasks'
            , (select (case when count(t.taskid) > 0 then 'Overdue' else 'all' end)
               from Task t with (nolock)
    from project p with (nolock)
    -- there are some additional joined tables here ...

如您所见,我一次又一次地选择同一子查询的子集计数,查询本质上是:

select * from Task where IsDeleted = 0 and Task.PrimarySearchEntityId = p.ProjectId

我如何才能重新使用此结果集,然后从那里进行过滤? 我可以使用cte,但是问题是我需要了解Advanced的ProjectId,所以这行不通。 我不想使用联接,因为我希望此视图中的每个记录成为该项目的唯一记录。 这里有什么建议吗? 我可以将这些Tasks分组或重用结果集的某种方式?

您可以使用相关的子查询来计算所有总数:

create view [schema].[vName]
as

select p.ProjectId as 'ProjectId',
    tsk.Total_Tasks, tsk.Assigned_Tasks, tsk.Completed_Tasks, tsk.Remaining_Tasks,
    ...
from project p with (nolock)
    cross apply (
        select count(*) as [Total_Tasks],
            count(case when t.taskowner != 'Unassigned' then 1 end) as [Assigned_Tasks],
            count(case when t.TaskStatusId in (400, 500) then 1 end) as [Completed_Tasks],
            count(case when t.TaskStatusId not in (400, 500) then 1 end) as [Remaining_Tasks],
            -- Et cetera, ad infinitum...
        from dbo.Task t
        where t.PrimarySearchEntityId = p.ProjectId and t.IsDeleted = 0
    ) tsk
-- there are some additional joined tables here ...

由于只有一组分组,因此查询可以简化为:

select p.ProjectId, 
    count(t.TaskId) as Total_Tasks,
    count(case when t.taskowner != 'Unassigned' then 1 end) as Assigned_Tasks,
    count(case when t.TaskStatusId in (400, 500) then 1 end) as Completed_Tasks,
    count(case when t.TaskStatusId not in (400, 500) then 1 end) as Remaining_Tasks,
    count(case when t.DueDate < getutcdate() and t.TaskStatusId not in (400, 500) then 1 end) as Late_Tasks
from project p with (nolock)
left join dbo.Task t on t.PrimarySearchEntityId = p.ProjectId and t.IsDeleted = 0
group by p.ProjectId

如果您要分组的表有多个,那么您就必须按照其他答案去一个子查询,尽管没有理由对左联接使用交叉应用。

select p.ProjectId, Total_Tasks, Assigned_Tasks, Completed_Tasks, Remaining_Tasks, Late_Tasks
from project p
left join (
    select
        PrimarySearchEntityId,
        count(TaskId) as Total_Tasks,
        count(case when taskowner != 'Unassigned' then 1 end) as Assigned_Tasks,
        count(case when skStatusId in (400, 500) then 1 end) as Completed_Tasks,
        count(case when t.TaskStatusId not in (400, 500) then 1 end) as Remaining_Tasks,
        count(case when DueDate < getutcdate() and TaskStatusId not in (400, 500) then 1 end) as Late_Tasks
    from dbo.Task
    where IsDeleted=0
    group by PrimarySearchEntityId
) t on t.PrimarySearchEntityId = p.ProjectId 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM