2012-04-07 13 views
2

Ich habe eine Reihe von Berichten, um zu kämpfen, die die Summe der verbrannten Kalorien in 15 Minuten-Schritten für „Teams“ und „Benutzer gibt.TSQL Gruppierung nach Zeit mit Start- und Enddaten

Die Tabellen ich verwende sind wie folgt:

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); 

einer der Berichte möchte ich zeigt die Kalorien von einem bestimmten Team, in bestimmten Schritten und Zeitrahmen so verbrannt erzeugen, wenn ich das A-Teams der Kalorien in Form von 8 verbrannt angezeigt werden soll. Bis 18 Uhr an einem bestimmten Tag in 15-Minuten-Schritten sollte der Bericht so aussehen:
TheDt Team Calories
08.00.00 A-Team 860
08.15.00 A-Team 860
08.30.00 A-Team 1810
08.45.00 A-Team 1810
09.00.00 A-Team 1810
09.15.00 A-Team 1810
09.30.00 A-Team 1810
09.45.00 A-Team 950
10: 00:00 Uhr A-Team 950
10:15:00 Uhr A-Team 950
10:30:00 Uhr A-Team 950
10:45: 00.00 A-Team 950
11.00.00 A-Team 0
....
02.30.00 A-Team 0
02.45.00 A-Team 536
15.00.00 A-Team 536
15.15.00 A-Team 536
15.30.00 A-Team 0
...
06.00.00 A-Team 0

In meiner Forschung entdeckte ich, dass die Verwendung einer Tabelle zur Unterstützung der Inkremente (15 Minuten) und der Beitritt zu meiner Workouts-Tabelle helfen sollte. Also, habe ich die folgende Tabelle:

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; 

Ich versuchte dann, zu meiner Traininge Tabelle mit dem folgenden beitreten:

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; 

Das ist so nah wie ich in der Lage gewesen, auf die Lösung zu kommen. Aber ich habe ein paar Probleme:

1) Ich habe nicht herausgefunden, wie Sie den Team_Name aus der JOIN-Anweisung beitreten.

2) Der CalorieCnt, auch wenn er mit Team_Name anstelle von User_ID aggregiert wurde, zeigt für jeden Zeitraum dieselben Werte. Es sammelt nicht die Summen für jede gegebene Zeit, einschließlich der Zeiten, wenn es 0 sein sollte.

Ich denke, eines der Probleme ist, dass ich den Vergleich nicht bekommen kann, wie viele Kalorien bei 08:45 verbrannt wurden : 00 AM, weil zu dieser Zeit kein Workout gestartet/beendet wurde. Ich habe mir das schon eine Weile angesehen und bin ratlos. Jede Hilfe, die diese Berichte für einen einzelnen Benutzer und ein Team benötigt, wäre sehr willkommen!

+0

Der Wert in "Kalorien" bedeutet "Kalorien in 15 Minuten verbrannt" oder "Kalorien verbrannt während des Trainings"? – Quassnoi

+0

Workouts.Calories ist die Anzahl der während des Trainings verbrannten Kalorien. Der Bericht ist nicht so genau wie es sein könnte, da Workouts.Calories für das gesamte Training ist. Und der erzeugte Bericht ist für 15-Minuten-Intervalle. Ich erkenne das. Aber das sind die Daten, mit denen ich arbeiten muss. Und fügt dem Bericht einen Mehrwert hinzu. – user1319487

Antwort

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

Das ist wirklich nah! Sie haben den Beitritt des Problems Team_Name gelöst. Und die Aggregation ist korrekt, wenn Werte vorhanden sind. Ich möchte jedoch in der Lage sein, diese Zeiten in dem Bereich anzuzeigen, in dem der Wert von Kalorien 0 ist. – user1319487

+0

@ user1319487: natürlich, ersetzen Sie 'JOIN' durch' LEFT JOIN' in der inneren Abfrage. – Quassnoi

+0

Danke für die Quassnoi ... hat nicht so funktioniert. Aber ich schätze deine Hilfe! – user1319487

0

Versuchen Sie diese. Ich habe den CTE aus dem obigen Beispiel modifiziert, um alle Teams für alle Bereiche zu erhalten, selbst wenn die Kalorien 0 sind.

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) 

Welche erzeugt diese Ausgabe. Wenn ich verstehe, wonach Sie suchen, denke ich, dass dies Ihnen gibt, was Sie wollen.

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) 

Ist das wonach Sie suchen?

+0

Ja. Danke Steve! Ich schätze die Hilfe. – user1319487