[英]SQL query to calculate subtotal and grand total
I have following sample data:我有以下示例数据:
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
I would like to produce:我想生产:
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
I would like to get the sample output using SQL Query RollUp statement because performance is issue.我想使用 SQL Query RollUp 语句获取示例输出,因为性能是问题。 As TimeSheet Table will have millions of records.由于时间表表将有数百万条记录。 Is there any other way of doing this writing procedure or function instead of views?有没有其他方法可以代替视图来执行此编写过程或函数? Thank you for your help in advance Regards Ishwor提前感谢您的帮助 Ishwor
I think you can't mix results with data in the same table.我认为您不能将结果与同一个表中的数据混合。 Also, if this is possible, I think it's not a good idea.另外,如果这是可能的,我认为这不是一个好主意。
You can get the subtotal with a query similar to this:您可以使用类似于此的查询获取小计:
select RosterID, EmpID, RosterDate, sum(Total)
from tableRoster group by RosterID, EmpID, RosterDate;
The total is easier, you can get it with this:总数更容易,您可以通过以下方式获得:
select sum(Total) from tableRoster;
I tried to utilize your preferred method ... although there are probably some kinks to work out.我尝试使用你喜欢的方法......尽管可能有一些问题需要解决。 Apologies if it isn't working 100% as hoped for, but maybe you can take the below and modify it to your needs.如果它没有像预期的那样 100% 工作,请道歉,但也许您可以采用以下内容并根据您的需要对其进行修改。
My suspicion is that including the start/end dates in there will result in trivial sub-groupings which can be ignored.我怀疑在那里包含开始/结束日期会导致可以忽略的微不足道的子分组。 I realize not testing my solution fully is not ideal for this forum ... sorry for this ... just kind of whipped it up on a whim as a quick distraction from work.我意识到不完全测试我的解决方案对于这个论坛来说并不理想......对此感到抱歉......只是一时兴起,以分散工作的注意力。 Good luck to you.祝你好运。
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
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.