2014-12-04 51 views
1

我有一個基於Web的報表,它從我們的SQL服務器中提取信息負載,並想知道向該SQL查詢添加「總計」行的最佳方式底部。該查詢充滿了子查詢,所以我不確定在底部添加彙總行的最佳方式。將總行添加到SQL查詢底部的方法

我知道「最好」的方法是在表現層做這件事,但我對錶示層有着甜美的FA知識(因爲它已經離開了而沒有人擁有相同的東西技能...!)

  SELECT 
      dbo.Groups.GroupName, dbo.UserGroups.GroupId, dbo.Users.UserName + ' ' + dbo.Users.Surname AS Consultant, 
       dbo.UserGroups.UserId, 
       (SELECT COUNT(*) AS ManagerCount 
       FROM  dbo.ClientContacts 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS ManagersAdded, 
       (SELECT COUNT(*) AS InterviewCount 
       FROM  dbo.Interviews 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (InterviewTypeId = 1) AND (Createdon BETWEEN @startDate AND @endDate)) AS FirstInterviewCount, 
       (SELECT COUNT(*) AS InterviewCount 
       FROM  dbo.Interviews AS Interviews_1 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (InterviewTypeId in (1,3,4)) AND (Createdon BETWEEN @startDate AND @endDate)) AS InterviewCount, 
       (SELECT COUNT(*) AS InterviewCount 
       FROM  dbo.Interviews AS Interviews_1 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (InterviewTypeId in (2)) AND (Createdon BETWEEN @startDate AND @endDate)) AS TelephoneCount, 
       (SELECT COUNT(*) AS DMSpokenTo 
       FROM  dbo.NotebookItems 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (NotebookTypeId = 56) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS DMSpokenTo, 
       (SELECT COUNT(*) AS Appspokento 
       FROM  dbo.NotebookItems 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (NotebookTypeId = 85) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS AppSpokenTo, 
       (SELECT COUNT(*) AS Marketed 
       FROM  dbo.NotebookItems AS NotebookItems_1 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (NotebookTypeId = 124) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS Marketed, 
       (SELECT COUNT(*) AS CVSent 
       FROM  dbo.ApplicantActions 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (StatusId <> 28) AND (JobId IS NOT NULL) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS CVSent, 
       (SELECT COUNT(*) AS CVSent 
       FROM  dbo.ApplicantActions 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS Speccv, 
       (SELECT COUNT(*) AS Meetings 
       FROM  dbo.DiaryEvents 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (EventTypeID = 29) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS Meetings, 
       (SELECT COUNT(*) AS VacanciesAdded 
       FROM  dbo.Jobs 
       WHERE (CreatedUserId = dbo.Users.UserId) AND (CreatedOn BETWEEN @startDate AND @endDate)) AS VacanciesAdded, 
       (SELECT SUM(pc.CommissionPerc/100) AS PermPlacements 
       FROM  dbo.Placements 
       INNER JOIN PlacementConsultants pc on placements.PlacementID = pc.PlacementId 
       INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = placements.PlacementID 
       WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (placements.CreatedOn BETWEEN @startDate AND @endDate) AND (PlacementTypeId <> 6)) AS [Perm Placements], 
       (SELECT SUM(PlacementFee/100 * pc.CommissionPerc) AS PermFee 
       FROM  dbo.Placements 
       INNER JOIN PlacementConsultants pc on placements.PlacementID = pc.PlacementId 
       INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = placements.PlacementID 
       WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (placements.CreatedOn BETWEEN @startDate AND @endDate) AND (PlacementTypeId <> 6)) AS [Perm Fee], 
       (SELECT SUM(pc.CommissionPerc/100) AS ContractPlacements 
       FROM  dbo.Placements 
       INNER JOIN PlacementConsultants pc on placements.PlacementID = pc.PlacementId 
       INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = placements.PlacementID 
       WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (placements.CreatedOn BETWEEN @startDate AND @endDate) AND (PlacementTypeId = 6)) AS [Contract Placements], 
       (SELECT SUM(dbo.CONTRACT_NETT_VALUE_FOR_INITIAL_PLACEMENT(Placements_1.PlacementID)/100 * pc.CommissionPerc) AS ContractFee 
       FROM  dbo.Placements AS Placements_1 
       INNER JOIN PlacementConsultants pc on Placements_1.PlacementID = pc.PlacementId 
       INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = Placements_1.PlacementID 
       WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (Placements_1.CreatedOn BETWEEN @startDate AND @endDate) AND (PlacementTypeId = 6)) AS [Contract Value] 


      FROM dbo.Groups INNER JOIN 
        dbo.UserGroups ON dbo.Groups.GroupId = dbo.UserGroups.GroupId INNER JOIN 
        dbo.Users ON dbo.UserGroups.UserId = dbo.Users.UserId 
      WHERE (  
        (dbo.Users.Inactive = 'N') AND (dbo.UserGroups.GroupId = @GroupId)) 
        and users.userid not in (select userid from UserGroups where GroupId = 57) 

一種方法可以做一個UNION,然後在另一組子查詢的增加,但是這會帶來麻煩和可笑的長篇大論的肯定?

有沒有比這更好的方式呢?

+0

您是否嘗試過使用公用表表達式? [Here](http://technet.microsoft.com/en-us/library/ms190766(v = sql.105).aspx)是一個相同的文檔。 – rusk 2014-12-04 10:54:04

+0

@rusk使用CTE和表變量有什麼區別? – franglais 2014-12-04 11:41:18

+1

[This](http://thinknook.com/sql-server-table-variable-vs-temporary-table-vs-cte-2012-01-12/)可能會爲您清除它。 – rusk 2014-12-04 12:25:19

回答

2
  1. 嘗試ROLLUP
  2. 出於性能方面的原因,我會考慮使用表變量或臨時表來避免同一表的多個查詢。此外,表變量和臨時表可以至少有一個主鍵,而公用表表達式不會編入索引。

例如:

DECLARE @GroupName VARCHAR(100) 
SELECT @GroupName = g.GroupName 
FROM dbo.Groups g 
WHERE g.GroupId = @GroupId 

DECLARE @Users TABLE 
(
    UserId INT NOT NULL PRIMARY KEY, 
    Consultant VARCHAR(100) NOT NULL 
) 

INSERT @Users (UserId, Consultant) 
SELECT u.UserId, u.UserName + ' ' + u.Surname 
FROM dbo.Users u 
INNER JOIN dbo.UserGroups ug ON u.UserId = ug.UserId AND ug.GroupId = @GroupId 
WHERE u.Inactive = 'N' 
AND NOT EXISTS (SELECT 1 FROM dbo.UserGroups ne 
        WHERE u.UserId = ne.UserId 
        AND ne.GroupId = 57) 

DECLARE @ClientContacts TABLE 
(
    UserId INT NOT NULL PRIMARY KEY, 
    ManagerCount INT NOT NULL 
) 

INSERT @ClientContacts (UserId, ManagerCount) 
SELECT u.UserId, COUNT(*) 
FROM @Users u 
INNER JOIN dbo.ClientContacts cc ON cc.CreatedUserId = u.UserId AND cc.CreatedOn BETWEEN @startDate AND @endDate 
GROUP BY u.UserId 

DECLARE @Interviews TABLE 
(
    UserId INT NOT NULL, 
    InterviewTypeId INT NOT NULL, 
    InterviewCount INT NOT NULL, 
    PRIMARY KEY (UserId, InterviewTypeId) 
) 

INSERT @Interviews (UserId, InterviewTypeId, InterviewCount) 
SELECT u.UserId, i.InterviewTypeId, COUNT(*) 
FROM @Users u 
INNER JOIN dbo.Interviews i ON u.UserId = i.CreatedUserId AND i.InterviewTypeId BETWEEN 1 AND 4 AND i.CreatedOn BETWEEN @StartDate AND @EndDate 
GROUP BY u.UserId, i.InterviewTypeId 

-- Rest is an exercise for the reader, but: 

SELECT @GroupName AS GroupName, 
     @GroupId AS GroupId, 
     CASE GROUPING(u.UserId) WHEN 1 THEN NULL ELSE MIN(u.Consultant) END AS Consultant, 
     u.UserId, 
     SUM(COALESCE(cc.ManagerCount, 0)) AS ManagersAdded, 
     SUM(COALESCE(ip.[1], 0)) AS FirstInterviewCount, 
     SUM(COALESCE(ip.[1], 0) + COALESCE(ip.[3], 0) + COALESCE(ip.[4], 0)) AS InterviewCount, 
     SUM(COALESCE(ip.[2], 0)) AS TelephoneCount 
FROM @Users u 
LEFT JOIN @ClientContacts cc ON u.UserId = cc.UserId 
LEFT JOIN (SELECT i.UserId, i.InterviewTypeId, i.InterviewCount 
      FROM @Interviews i) AS ii 
      PIVOT (SUM(InterviewCount) FOR InterviewTypeId IN ([1], [2], [3], [4])) AS ip ON u.UserId = ip.UserId 
GROUP BY ROLLUP(u.UserId) 
ORDER BY GROUPING(u.UserId), u.UserId