获取复杂sql数据的最佳方法(性能问题)

时间:2016-12-23 11:29:31

标签: sql linq-to-sql

您好我有一个timeLogs表,其中包含列(id,startTime,EndTime,User_Id,Client_Id,Project_Id,Task_Id,TotalHours)

我需要输出包含projectids,taskids,datefrom,datetill过滤器的列(Client,Project,Task,NoOfResources,TotalTime)样本输出和表结构如下所示

enter image description here

此处User_Id,Client_Id,Task_Id,Project_Id是包含用户,客户,任务,项目的外键

这里的资源数是用户数

我是通过存储过程来完成的:

ALTER procedure [dbo].[GetProjectUtilizationReport] 
    (@DateFrom datetime =null,
     @DateTill datetime = null, 
     @TaskTypeIds nvarchar(max) = null,
     @TaskIds nvarchar(max) = null,
     @UserIds  nvarchar(max) = null,
     @ProjectIds  nvarchar(max) = null)
AS
BEGIN
    CREATE TABLE #TempTable(id int,
                            ProjectId int,
                            ClientId int,
                            UserId int,
                            TaskId int,
                            TotalHours numeric(18,2),
                            StartTime datetime,
                            TaskTypeId int)

    --- create a temp table with data dump
    INSERT INTO #TempTable(Id, ProjectId, ClientId, UserId, TaskId, TotalHours, StartTime, TaskTypeId) 
        SELECT 
            tl.id,Project_Id, Client_Id,
            User_Id, Task_Id, TotalHours,
            StartTime, TaskType_Id 
        FROM 
            TimeLogs tl 
        JOIN 
            Tasks t ON tl.Task_Id = t.Id

    --apply filter to temp table
    IF (@DateFrom IS NOT NULL)
        DELETE FROM #TempTable 
        WHERE StartTime < @DateFrom

    IF (@DateTill IS NOT NULL)
        DELETE FROM #TempTable 
        WHERE StartTime > @DateTill

    IF (@TaskTypeIds IS NOT NULL)
        DELETE FROM #TempTable 
        WHERE TaskTypeId NOT IN (SELECT Item FROM dbo.SplitString(@TaskTypeIds, ','))

    IF (@TaskIds IS NOT NULL)
        DELETE FROM #TempTable 
        WHERE TaskId NOT IN (SELECT Item FROM dbo.SplitString(@TaskIds, ','))

    IF (@UserIds IS NOT NULL)
        DELETE FROM #TempTable 
        WHERE UserId NOT IN (SELECT Item FROM dbo.SplitString(@UserIds, ','))

    IF (@ProjectIds IS NOT NULL)
        DELETE FROM #TempTable 
        WHERE ProjectId NOT IN (SELECT Item FROM dbo.SplitString(@ProjectIds, ','))

    --finaly select data
    SELECT 
        p.Name as Project, c.Name as Client,
        tl.TaskId, t.Name as Task,
        SUM(TotalHours) as Totalhours,
        COUNT(DISTINCT tl.UserId) as NoOfResources,
        c.Id as ClientId 
    FROM
        #TempTable tl
    JOIN
        Tasks t ON tl.TaskId = t.Id 
    JOIN
        Clients c ON c.Id = tl.ClientId
    JOIN
        Projects p ON tl.ProjectId = p.Id 
    GROUP BY
        tl.TaskId, c.id, c.Name, p.Name, t.Name 

    --drop temp table 
    DROP TABLE #TempTable
END

我认为可能有更好的方法 - 类似于观点等,但我没有任何想法。

可以将数据放在插入等的其他表中。

请提出您的建议,表明我可以尽可能快地获得结果。

1 个答案:

答案 0 :(得分:2)

我经常尽量避免使用#tables。

SELECT  c.Name AS Client, p.Name AS Project, t.Name AS Task, COUNT(DISTINCT tl.User_Id) AS NoOfResources, SUM(TotalHours) AS Totalhours         
FROM TimeLogs tl
INNER JOIN Tasks t ON tl.Task_Id =t.Id 
INNER JOIN Clients c ON c.Id =tl.Client_Id
INNER JOIN Projects p ON tl.Project_Id =p.Id 
INNER JOIN (SELECT Item FROM dbo.SplitString(ISNULL(@UserIds, ''), ',')) users ON users.Item = tl.User_Id OR @UserIds IS NULL
INNER JOIN (SELECT Item FROM dbo.SplitString(ISNULL(@TaskTypeIds, ''), ',')) tasktypes ON tasktypes.Item = tl.TaskType_Id OR @TaskTypeIds IS NULL
INNER JOIN (SELECT Item FROM dbo.SplitString(ISNULL(@TaskIds, ''), ',')) tasks ON tasks.Item = tl.Task_Id OR @TaskIds IS NULL
INNER JOIN (SELECT Item FROM dbo.SplitString(ISNULL(@ProjectIds, ''), ',')) projects ON projects.Item = tl.Project_Id OR @ProjectIds IS NULL
WHERE (@DateFrom IS NULL OR StartTime < @DateFrom)
AND (@DateTill IS NULL OR StartTime > @DateTill)
GROUP BY c.Id, c.Name, p,Id, p.Name, t.Id, t.Name