2

「チーム」と「ユーザー」の 15 分ごとの消費カロリーの合計を示す一連のレポートを作成するのに苦労しています。

私が使用しているテーブルは次のとおりです。

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

私が生成したいレポートの 1 つは、特定のチームが消費したカロリーを、特定の増分と時間枠で表示します。したがって、ある日の午前 8 時から午後 6 時までの A チームの消費カロリーを 15 分刻みで表示したい場合、レポートは次のようになります。
TheDt Team Calories 08:00:00
AM A-Team 860
08: 15:00 AM A チーム 860
08:30:00 AM A チーム 1810
08:45:00 AM A チーム 1810
09:00:00 AM A チーム 1810
09:15:00 AM A チーム 1810
09: 30:00 AM A チーム 1810
09:45:00 AM A チーム 950
10:00:00 AM A チーム 950
10:15:00 AM Aチーム 950 10:30:00 AM A
チーム 950
10:45:00 AM A チーム 950
11:00:00 AM A チーム 0
....
02:30:00 PM A チーム 0
02:45:00 PM A チーム 536
03:00:00 PM A チーム 536
午後 3:15:00 A チーム 536
午後 3:30:00 A チーム 0
...
午後 6:00:00 A チーム 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;

次に、Workouts テーブルを次のように結合しようとしました。

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 は、User_ID ではなく Team_Name で集計された場合でも、各期間で同じ値を示します。合計が 0 になるはずの時間も含め、所定の時間ごとに合計が適切に集計されていません。

問題の 1 つは、午前 08:45:00 に開始/終了したワークアウトがないため、午前 8 時 45 分に燃焼したカロリー数を比較できないことだと思います。私はしばらくこれを見ていて、困惑しています。これらのレポートを個々のユーザーおよびチームで機能させるための助けをいただければ幸いです。

4

2 に答える 2

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)
于 2012-04-07T20:26:16.003 に答える
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)

これはあなたが探しているものですか?

于 2012-04-09T02:46:57.783 に答える