SQL查询计算小计和总计

时间:2016-05-25 14:36:53

标签: sql

我有以下示例数据:

TimeSheetID RosterID    EmpID   RosterDate  StartTime   EndTime Total
       1         101    1001    2016-05-24  07:00   15:00   8
       2         101    1001    2016-05-24  16:00   21:00   5
       3         101    1002    2016-05-24  07:00   15:00   8
       4         101    1003    2016-05-24  07:00   15:00   8
       5         101    1001    2016-05-25  07:00   15:00   8
       6         101    1002    2016-05-25  07:00   15:00   8
       7         101    1002    2016-05-25  16:00   22:00   6
       8         101    1003    2016-05-25  07:00   15:00   8
       9         101    1001    2016-05-26  07:00   14:00   7
       10        101    1001    2016-05-26  15:00   21:00   6
       11        101    1002    2016-05-26  07:00   15:00   8
       12        101    1003    2016-05-26  07:00   15:00   8
       13        101    1001    2016-05-27  07:00   15:00   8
       14        101    1002    2016-05-27  07:00   15:00   8
       15        101    1003    2016-05-27  07:00   15:00   8
       16        101    1001    2016-05-28  07:00   15:00   8
       17        101    1002    2016-05-28  07:00   15:00   8
       18        101    1003    2016-05-28  07:00   15:00   8
       19        101    1001    2016-05-29  07:00   15:00   8
       20        101    1002    2016-05-29  07:00   15:00   8
       21        101    1003    2016-05-29  07:00   15:00   8
       22        102    1001    2016-05-30  07:00   15:00   8

我想制作:

ID       RosterID   EmpID   RosterDate  StartTime   EndTime Total
1        101        1001    2016-05-24  07:00        15:00  8
2        101        1001    2016-05-24  16:00        21:00  5
3        101        1001    2016-05-24  Null         Null   13
4        101        1002    2016-05-24  07:00        15:00  8
5        101        1003    2016-05-24  07:00        15:00  8
6        101        1001    2016-05-25  07:00        15:00  8
7        101        1002    2016-05-25  07:00        15:00  8
8        101        1002    2016-05-25  16:00        22:00  6
9        101        1002    2016-05-25  Null         Null   14
10       101        1003    2016-05-25  07:00        15:00  8
11       101        1001    2016-05-26  07:00        14:00  7
12       101        1001    2016-05-26  15:00        21:00  6
13       101        1001    2016-05-26  Null         Null   13
14       101        1002    2016-05-26  07:00        15:00  8
15       101        1003    2016-05-26  07:00        15:00  8
16       101        1001    2016-05-27  07:00        15:00  8
17       101        1002    2016-05-27  07:00        15:00  8
18       101        1003    2016-05-27  07:00        15:00  8
19       101        1001    2016-05-28  07:00        15:00  8
20       101        1002    2016-05-28  07:00        15:00  8
21       101        1003    2016-05-28  07:00        15:00  8
22       101        1001    2016-05-29  07:00        15:00  8
23       101        1002    2016-05-29  07:00        15:00  8
24       101        1003    2016-05-29  07:00        15:00  8
25       102        1001    2016-05-30  07:00        15:00  8
26       Total      Null    Null        Null         Null   168

我想使用SQL Query RollUp语句获取示例输出,因为性能有问题。由于TimeSheet表将有数百万条记录。有没有其他方式来执行此编写过程或函数而不是视图? 提前谢谢你的帮助 问候 Ishwor

3 个答案:

答案 0 :(得分:1)

我认为你不能将结果与同一个表中的数据混合在一起。 此外,如果这是可能的,我认为这不是一个好主意。

您可以使用与此类似的查询获取小计:

select RosterID, EmpID, RosterDate, sum(Total) 
from tableRoster group by RosterID, EmpID, RosterDate;

总数更容易,你可以用它来获得它:

select sum(Total) from tableRoster;

答案 1 :(得分:0)

我尝试使用您首选的方法......虽然可能会有一些问题需要解决。如果它没有像预期的那样100%工作,请道歉,但也许您可以采取以下措施并根据您的需要进行修改。

我怀疑在那里包括开始/结束日期将导致可以忽略的微不足道的子分组。我意识到没有完全测试我的解决方案对于这个论坛来说并不理想...对不起...只是一种随心所欲的鞭打它作为工作的快速分心。祝你好运。

SELECT 
 CASE WHEN (GROUPING(RosterID) = 1) THEN 'Total' 
      ELSE RosterID 
 END AS RosterID
,CASE WHEN (GROUPING(EmpID) = 1) AND (GROUPING(RosterID) = 1) THEN NULL 
      ELSE EmpID 
 END AS EmpID
,CASE WHEN (GROUPING(RosterDate) = 1) AND (GROUPING(RosterID) = 1) THEN NULL 
      ELSE RosterDate 
 END AS RosterDate
,CASE WHEN (GROUPING(RosterDate) = 1) THEN NULL 
      ELSE StartTime 
 END AS StartTime
,CASE WHEN (GROUPING(RosterDate) = 1) THEN NULL 
      ELSE EndTime 
 END AS EndTime
,Sum(Total) AS Total
FROM Table a
GROUP BY 
 ROLLUP(RosterID ,RosterDate ,EmpID ,StartTime ,EndTime)
ORDER BY
 RosterID, RosterDate, EmpID

答案 2 :(得分:0)

I tried to resolve with basic loop as below

-- ASSUMED THAT DATA IS INSERTED INTO Roster TABLE 
-- STP_01: BY SEEING DATA COLUMNS ARE CREATED AS BELOW
CREATE TABLE Roster(TimeSheetID INT IDENTITY(1,1),RosterID INT ,EmpID INT , RosterDate DATE ,StartTime TIME, EndTime TIME, Total INT)

SET IDENTITY_INSERT Roster ON
GO

-- STP_02:INSERTING PROVIDED DATA AS BELOW
INSERT INTO Roster(TimeSheetID,RosterID,EmpID,RosterDate,StartTime,EndTime,Total)
VALUES(1 ,101,1001,'2016-05-24','07:00', '15:00', 8),
(2 ,101,1001,'2016-05-24','16:00', '21:00', 5),
(3 ,101,1002,'2016-05-24','07:00', '15:00', 8),
(4 ,101,1003,'2016-05-24','07:00', '15:00', 8),
(5 ,101,1001,'2016-05-25','07:00', '15:00', 8),
(6 ,101,1002,'2016-05-25','07:00', '15:00', 8),
(7 ,101,1002,'2016-05-25','16:00', '22:00', 6),
(8 ,101,1003,'2016-05-25','07:00', '15:00', 8),
(9 ,101,1001,'2016-05-26','07:00', '14:00', 7),
(10,101,1001,'2016-05-26','15:00', '21:00', 6),
(11,101,1002,'2016-05-26','07:00', '15:00', 8),
(12,101,1003,'2016-05-26','07:00', '15:00', 8),
(13,101,1001,'2016-05-27','07:00', '15:00', 8),
(14,101,1002,'2016-05-27','07:00', '15:00', 8),
(15,101,1003,'2016-05-27','07:00', '15:00', 8),
(16,101,1001,'2016-05-28','07:00', '15:00', 8),
(17,101,1002,'2016-05-28','07:00', '15:00', 8),
(18,101,1003,'2016-05-28','07:00', '15:00', 8),
(19,101,1001,'2016-05-29','07:00', '15:00', 8),
(20,101,1002,'2016-05-29','07:00', '15:00', 8),
(21,101,1003,'2016-05-29','07:00', '15:00', 8),
(22,102,1001,'2016-05-30','07:00', '15:00', 8)

SET IDENTITY_INSERT Roster OFF
GO

-- STP_03:CREATING Roster_1 TABLE TO INSERT PROCESSED DATA - NOT TOUCHING ORIGINAL TABLE
-- DROP TABLE Roster_1
CREATE TABLE [dbo].[Roster_1](
    [TimeSheetID] [int] NULL,
    [RosterID] [varchar](15) NULL,  -- CHANGED TO VARCHAR(15) TO PROVIDE GrpToal/GndTotal
    [EmpID] [varchar](15) NULL,     -- CHANGED TO VARCHAR(15) TO PROVIDE GrpToal/GndTotal
    [RosterDate] [date] NULL,
    [StartTime] [time](7) NULL,
    [EndTime] [time](7) NULL,
    [Total] [int] NULL
) 

-- STP_04: SOME VARIABLES TO PROCESS LOOP
DECLARE @MinRosterDate DATE,@MaxRosterDate DATE,@MinEmpId INT,@MaxEmpID INT,@kMinEmpId INT
SELECT 
        @MinRosterDate = MIN(RosterDate),   -- 2016-05-24
        @MaxRosterDate = MAX(RosterDate),   -- 2016-05-30
        @MinEmpId = MIN(EmpID),             -- 1001
        @MaxEmpID = MAX(EmpID)              -- 1003
FROM Roster

-- STP_05: RE-RUNNABLE
TRUNCATE TABLE Roster_1

SET @kMinEmpId  = @MinEmpId -- RESERVING THIS VALUE

-- STEP_06: ENTERING LOOP
WHILE (@MinRosterDate<= @MaxRosterDate)     -- OUTER LOOP
BEGIN
    WHILE(@MinEmpId <= @MaxEmpID)           -- INNER LOOP FOR ALL EMPID WORKED DURING THIS TIME FRAME
    BEGIN
        IF EXISTS(SELECT 1 FROM Roster WHERE RosterDate = @MinRosterDate AND EmpID = @MinEmpId) -- CHECKING WHETHER DATA EXISTS
        BEGIN
            INSERT INTO Roster_1    
            SELECT TimeSheetID,CONVERT(VARCHAR(7),RosterID),CONVERT(VARCHAR(7),EmpID),RosterDate,StartTime,EndTime,Total FROM Roster WHERE RosterDate = @MinRosterDate AND EmpID = @MinEmpId
            UNION
            SELECT null,'GrpTotalByEmpID',@MinEmpId,@MinRosterDate,null,null,SUM(Total)FROM Roster WHERE RosterDate = @MinRosterDate AND EmpID = @MinEmpId
        END 

        SET @MinEmpId = @MinEmpId + 1 -- BREAKING INNER LOOP
    END

    IF(@MinEmpId > @MaxEmpId)        -- RESTARING FROM FIRST EmpID
        SET @MinEmpId = @kMinEmpId

    INSERT INTO Roster_1
    SELECT null,null,'GrpTotalByDate',@MinRosterDate,null,null,SUM(Total) from Roster_1 where RosterID = 'GrpTotalByEmpID' and RosterDate = @MinRosterDate

    IF(@MinRosterDate = @MaxRosterDate)     -- CALCULATING Grand Total
    BEGIN
        INSERT INTO Roster_1
        SELECT null,'GrandTotal',null,null,null,null,SUM(Total) FROM Roster_1 WHERE TimeSheetID IS NULL AND EmpID = 'GrpTotalByDate'
    END

    SET @MinRosterDate = DATEADD(DD,1, @MinRosterDate) -- BREAKING OUTER LOOP

END

-- STP_07: READING PROCESSED DATA
SELECT * FROM Roster_1