2012-04-07 106 views
2

我一直在努力做的一組報道,讓熱量以15個分鐘爲增量燒燬的總和爲「團隊」和「用戶。TSQL分組的時間開始和結束日期

我使用的表如下:

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('Teams') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE Teams; 

CREATE TABLE Teams 
(
Team_ID int NOT NULL PRIMARY KEY IDENTITY (1,1), 
Team_Name varchar(100), 
Team_Description varchar(200) 
); 

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('Users') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE Users; 

CREATE TABLE Users 
(
User_ID int NOT NULL PRIMARY KEY IDENTITY (1,1), 
User_Name varchar(100) 
); 

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('Team_User') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE Team_User; 

CREATE TABLE Team_User 
(
Team_ID int, 
User_ID int 
); 

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('Workouts') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE Workouts; 

CREATE TABLE Workouts 
(
Workout_ID int NOT NULL PRIMARY KEY IDENTITY (1,1), 
User_ID int, 
Workout_Type int, 
Start_Time datetime, 
End_Time datetime, 
Calories float 
); 

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('LK_Workout_Type') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE LK_Workout_Type; 

CREATE TABLE LK_Workout_Type 
(
WT_ID int NOT NULL PRIMARY KEY IDENTITY (1,1), 
Workout_Name varchar (80), 
Workout_Description varchar(200) 
); 

INSERT INTO Teams (Team_Name, Team_Description) VALUES ('A Team', 'We are not vets.'); 
INSERT INTO Teams (Team_Name, Team_Description) VALUES ('Team Solo', 'One man. One team.'); 

INSERT INTO Users (User_Name) VALUES ('Frank Appleton'); 
INSERT INTO Users (User_Name) VALUES ('Tim Murdock'); 
INSERT INTO Users (User_Name) VALUES ('Tim Smith'); 

INSERT INTO Team_User (Team_ID, User_ID) Values (1,1); 
INSERT INTO Team_User (Team_ID, User_ID) Values (1,2); 
INSERT INTO Team_User (Team_ID, User_ID) Values (2,3); 

INSERT INTO LK_Workout_Type (Workout_Name, Workout_Description) VALUES ('Bike - Mountain','Trail riding.'); 
INSERT INTO LK_Workout_Type (Workout_Name, Workout_Description) VALUES ('Bike - Road','Road riding.'); 
INSERT INTO LK_Workout_Type (Workout_Name, Workout_Description) VALUES ('Elliptical','Standard elliptical'); 
INSERT INTO LK_Workout_Type (Workout_Name, Workout_Description) VALUES ('Running','Typical running'); 
INSERT INTO LK_Workout_Type (Workout_Name, Workout_Description) VALUES ('Treadmill','Treadmill running'); 
INSERT INTO LK_Workout_Type (Workout_Name, Workout_Description) VALUES ('Weights','Weightroom'); 

INSERT INTO Workouts (User_ID, Workout_Type, Start_Time, End_Time, Calories) VALUES (1,1,'3/10/2012 08:00:00 AM','3/10/2012 09:30:00 AM', 860); 
INSERT INTO Workouts (User_ID, Workout_Type, Start_Time, End_Time, Calories) VALUES (2,1,'3/10/2012 08:30:00 AM','3/10/2012 10:45:00 AM', 950); 
INSERT INTO Workouts (User_ID, Workout_Type, Start_Time, End_Time, Calories) VALUES (3,5,'3/10/2012 10:05:00 AM','3/10/2012 12:27:00 PM', 1917); 
INSERT INTO Workouts (User_ID, Workout_Type, Start_Time, End_Time, Calories) VALUES (1,5,'3/10/2012 02:38:00 PM','3/10/2012 03:17:00 PM', 536); 

有一個問題我想生成顯示由給定團隊燃燒的卡路里的報告,在特定的增量和時限所以,如果我想要顯示從8燒燬A-隊的卡路里。上午到下午6點在給定的一天,以15分鐘爲增量,報告應該是這樣的:
TheDt Team Calories
上午八時00分零零秒A-隊860
上午08點15分○○秒A-隊860
上午08時30分00秒A-1810隊
上午8時45分○○秒A-1810隊
上午9時00分〇〇秒A-1810隊
上午9點15分00秒A-1810隊
上午9點30分○○秒A-1810隊
上午09時45分○○秒A-950隊
10: 00:00 AM A-950隊
上午10點一十五分00秒A-950隊
上午十時三十分00秒A-950隊
10:45:上午12點A-950隊
上午11時00分00秒A-隊0
....
下午2點30分〇〇秒A-隊0
下午2點45分00秒A-隊536
下午3點00分〇〇秒特攻隊536
下午3點15分零零秒攻隊536
下午3時30分○○秒A-隊0
...
下午6時00分00秒特攻隊0

在我的研究中,我發現使用表格來支持增量(15分鐘)並將其加入到我的鍛鍊表格中應該會有所幫助。所以,我創建瞭如下表:

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('Tally') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE Tally; 

CREATE TABLE Tally 
    (N INT, 
    CONSTRAINT PK_Tally_N PRIMARY KEY CLUSTERED (N)) 

-----------Create and preset a loop counter 
DECLARE @Counter INT 
    SET @Counter = 0 

-----------Populate the table with 15 minute intervals between 2012 and 2017 
    WHILE @Counter <= 175299 
    BEGIN 
     INSERT INTO Tally (N) VALUES (@Counter) SET @Counter = @Counter + 1 
    END 

-----------Build the CalendarDT Table 
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('CalendarDT') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE CalendarDT; 

DECLARE @StartDT DATETIME; 

SELECT @StartDT = '2012-01-01T00:00:00'; 

SELECT DATEADD(mi,v.N*15,@StartDT) AS TheDT INTO CalendarDT FROM Tally v WHERE v.N BETWEEN 0 AND 175299; 

-----------Creating a clustered index for performance 
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('IDXC_CalendarDT_TheDT') AND OBJECTPROPERTY(id, 'IsIndex') = 1) 
DROP INDEX CalendarDT.IDXC_CalendarDT_TheDT; 

CREATE CLUSTERED INDEX IDXC_CalendarDT_TheDT ON CalendarDT (TheDT) 
GO 

-----------Drop the Tally table 
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id('Tally') AND OBJECTPROPERTY(id, 'IsTable') = 1) 
DROP TABLE Tally; 

然後我試圖加入我的訓練表具有以下:

SELECT CalendarDT.TheDT AS [Date], COALESCE(SUM(Workouts.Calories),0) AS CalorieCnt, Workouts.User_ID 
FROM CalendarDT 
     LEFT OUTER JOIN Workouts ON Workouts.Start_Time >= '03/10/2012 08:00:00 AM' AND Workouts.End_Time < '03/10/2012 06:00:00 PM' 
     AND CalendarDT.TheDT >= '03/10/2012 08:00:00 AM' AND CalendarDT.TheDT <= '03/10/2012 06:00:00 PM' 
WHERE Workouts.User_ID IN (SELECT User_ID FROM Team_User WHERE Team_ID = 1) 
GROUP BY CalendarDT.TheDT, Workouts.User_ID 
ORDER BY CalendarDT.TheDT; 

這是接近我已經能夠得出解決方案。但是,我有幾個問題:

1)我還沒有想出如何從JOIN語句中加入Team_Name。

2)CalorieCnt,即使它是由Team_Name而不是User_ID聚合顯示每個時間段相同的值。它不是在每個給定的時間內正確彙總總數,包括那些應該爲0的時間。

我認爲其中一個問題是,我無法比較說08:45有多少卡路里被燃燒:00 AM,因爲當時沒有鍛鍊開始/結束。 我一直在尋找這一段時間,我很難過。任何幫助獲得這些報告爲個人用戶和團隊工作將不勝感激!

+0

「卡路里」中的值是指「15分鐘內消耗的卡路里」或「鍛鍊期間消耗的卡路里」? – Quassnoi 2012-04-07 20:20:20

+0

Workouts.calories是鍛鍊過程中燃燒的卡路里數。由於Workouts.calories適用於整個鍛鍊,因此該報告不如其準確。並且,生成的報告每15分鐘一次。我意識到這一點。但是,這是我必須處理的數據。而且,確實爲報告增添了價值。 – user1319487 2012-04-07 20:21:47

回答

1
WITH ranges (st) AS 
     (
     SELECT CAST('2012-03-10 08:00:00' AS DATETIME) 
     UNION ALL 
     SELECT DATEADD(minute, 15, st) 
     FROM ranges 
     WHERE DATEADD(minute, 15, st) < CAST('2012-03-10 18:00:00' AS DATETIME) 
     ) 
SELECT st, team_name, calories 
FROM (
     SELECT st, team_id, COALESCE(SUM(calories), 0) AS calories 
     FROM ranges r 
     LEFT JOIN 
       workouts w 
     ON  start_time < DATEADD(minute, 15, st) 
       AND end_time > st 
     LEFT JOIN 
       team_user tu 
     ON  tu.user_id = w.user_id 
     GROUP BY 
       st, team_id 
     ) c 
LEFT JOIN 
     teams t 
ON  t.team_id = c.team_id 
ORDER BY 
     c.st, c.team_id 
OPTION (MAXRECURSION 0) 
+0

這真的很接近!你已經解決了Team_Name問題的加入。並且,當有值時聚合是正確的。但是,我希望能夠在卡路里值爲0的範圍內顯示那些時間。 – user1319487 2012-04-07 20:32:21

+0

@ user1319487:當然,對不起,只需在內部查詢中用'LEFT JOIN'替換'JOIN'即可。 – Quassnoi 2012-04-08 10:21:53

+0

感謝Quassnoi ......並沒有完全按照這種方式工作。但是,我感謝您的幫助! – user1319487 2012-04-12 23:44:18

0

試試這個。我修改了上面例子中的CTE,即使卡路里爲0,也可以獲得所有範圍的所有團隊。

WITH ranges_CTE (st) AS 
(
    SELECT CAST('2012-03-10 08:00:00' AS DATETIME) 
    UNION ALL 
    SELECT DATEADD(minute, 15, st) 
    FROM ranges_CTE 
    WHERE DATEADD(minute, 15, st) < CAST('2012-03-10 18:00:00' AS DATETIME) 
), 
team_CTE (team_name, team_id) AS 
(
SELECT team_name, team_id 
    FROM teams 
), 
ranges_team_CTE (st, team_name, team_id) AS 
(
    SELECT r.st, t.team_name, t.team_id 
FROM ranges_CTE as r 
CROSS JOIN team_CTE as t 
) 
select t.st, t.team_name, isnull(c.calories, '') 
    from ranges_team_cte t 
    LEFT JOIN (
    SELECT st, team_id, COALESCE(SUM(calories), 0) AS calories 
    FROM ranges_CTE r 
    LEFT JOIN 
      workouts w 
    ON  start_time < DATEADD(minute, 15, st) 
      AND end_time > st 
    LEFT JOIN team_user tu 
    ON  tu.user_id = w.user_id 
    GROUP BY 
      st, team_id 
    ) c ON t.team_id = c.team_id AND t.st = c.st 
ORDER BY 
    t.st, t.team_id 
OPTION (MAXRECURSION 0) 

它產生這些輸出。如果我明白你在找什麼,我想這會給你你想要的。

st      team_name   calories 
----------------------- -------------------- ---------------------- 
2012-03-10 08:00:00.000 A Team    860 
2012-03-10 08:00:00.000 Team Solo   0 
2012-03-10 08:15:00.000 A Team    860 
2012-03-10 08:15:00.000 Team Solo   0 
2012-03-10 08:30:00.000 A Team    1810 
2012-03-10 08:30:00.000 Team Solo   0 
2012-03-10 08:45:00.000 A Team    1810 
2012-03-10 08:45:00.000 Team Solo   0 
2012-03-10 09:00:00.000 A Team    1810 
2012-03-10 09:00:00.000 Team Solo   0 
2012-03-10 09:15:00.000 A Team    1810 
2012-03-10 09:15:00.000 Team Solo   0 
2012-03-10 09:30:00.000 A Team    950 
2012-03-10 09:30:00.000 Team Solo   0 
2012-03-10 09:45:00.000 A Team    950 
2012-03-10 09:45:00.000 Team Solo   0 
2012-03-10 10:00:00.000 A Team    950 
2012-03-10 10:00:00.000 Team Solo   1917 
2012-03-10 10:15:00.000 A Team    950 
2012-03-10 10:15:00.000 Team Solo   1917 
2012-03-10 10:30:00.000 A Team    950 
2012-03-10 10:30:00.000 Team Solo   1917 
2012-03-10 10:45:00.000 A Team    0 
2012-03-10 10:45:00.000 Team Solo   1917 
2012-03-10 11:00:00.000 A Team    0 
2012-03-10 11:00:00.000 Team Solo   1917 
2012-03-10 11:15:00.000 A Team    0 
2012-03-10 11:15:00.000 Team Solo   1917 
2012-03-10 11:30:00.000 A Team    0 
2012-03-10 11:30:00.000 Team Solo   1917 
2012-03-10 11:45:00.000 A Team    0 
2012-03-10 11:45:00.000 Team Solo   1917 
2012-03-10 12:00:00.000 A Team    0 
2012-03-10 12:00:00.000 Team Solo   1917 
2012-03-10 12:15:00.000 A Team    0 
2012-03-10 12:15:00.000 Team Solo   1917 
2012-03-10 12:30:00.000 A Team    0 
2012-03-10 12:30:00.000 Team Solo   0 
2012-03-10 12:45:00.000 A Team    0 
2012-03-10 12:45:00.000 Team Solo   0 
2012-03-10 13:00:00.000 A Team    0 
2012-03-10 13:00:00.000 Team Solo   0 
2012-03-10 13:15:00.000 A Team    0 
2012-03-10 13:15:00.000 Team Solo   0 
2012-03-10 13:30:00.000 A Team    0 
2012-03-10 13:30:00.000 Team Solo   0 
2012-03-10 13:45:00.000 A Team    0 
2012-03-10 13:45:00.000 Team Solo   0 
2012-03-10 14:00:00.000 A Team    0 
2012-03-10 14:00:00.000 Team Solo   0 
2012-03-10 14:15:00.000 A Team    0 
2012-03-10 14:15:00.000 Team Solo   0 
2012-03-10 14:30:00.000 A Team    536 
2012-03-10 14:30:00.000 Team Solo   0 
2012-03-10 14:45:00.000 A Team    536 
2012-03-10 14:45:00.000 Team Solo   0 
2012-03-10 15:00:00.000 A Team    536 
2012-03-10 15:00:00.000 Team Solo   0 
2012-03-10 15:15:00.000 A Team    536 
2012-03-10 15:15:00.000 Team Solo   0 
2012-03-10 15:30:00.000 A Team    0 
2012-03-10 15:30:00.000 Team Solo   0 
2012-03-10 15:45:00.000 A Team    0 
2012-03-10 15:45:00.000 Team Solo   0 
2012-03-10 16:00:00.000 A Team    0 
2012-03-10 16:00:00.000 Team Solo   0 
2012-03-10 16:15:00.000 A Team    0 
2012-03-10 16:15:00.000 Team Solo   0 
2012-03-10 16:30:00.000 A Team    0 
2012-03-10 16:30:00.000 Team Solo   0 
2012-03-10 16:45:00.000 A Team    0 
2012-03-10 16:45:00.000 Team Solo   0 
2012-03-10 17:00:00.000 A Team    0 
2012-03-10 17:00:00.000 Team Solo   0 
2012-03-10 17:15:00.000 A Team    0 
2012-03-10 17:15:00.000 Team Solo   0 
2012-03-10 17:30:00.000 A Team    0 
2012-03-10 17:30:00.000 Team Solo   0 
2012-03-10 17:45:00.000 A Team    0 
2012-03-10 17:45:00.000 Team Solo   0 
(80 row(s) affected) 

這是你在找什麼?

+0

是的。謝謝史蒂夫!我很感激幫助。 – user1319487 2012-04-12 23:44:51

相關問題