So I have a couple tables structured similar to this:
所以我有几个类似于这样的表:
-
Run ([RunID], [PlayerID], [Score])
运行([RunID],[PlayerID],[得分])
-
Jump ([ID], [RunID], [Time], [Type])
跳转([ID],[RunID],[时间],[类型])
There are 4 "types" of time 2 "up" and 2 "down".
有4种“类型”的时间2“向上”和2“向下”。
I need to get the time between an "up" and an "down" on a given run.
我需要在给定的运行中获得“向上”和“向下”之间的时间。
Basically, during a "run" when a "jump" is made, I record an up time, and a down is recorded on a corresponding landing (only one pair per run). At the end of the "run" I need to display the total time "in air", as well as time per jump. I was thinking the best way to do this would be to dump into a temp table with the following structure:
基本上,在进行“跳跃”的“运行”期间,我记录一个上升时间,并且在相应的着陆上记录下来(每次运行只有一对)。在“跑步”结束时,我需要显示“在空中”的总时间,以及每次跳跃的时间。我认为最好的方法是转储到具有以下结构的临时表中:
@tempJump ([RunID], [TimeUp], [TimeDown])
Then I would have all the needed info to calculate and populate the necessary fields.
然后我将拥有所有需要的信息来计算和填充必要的字段。
So far I have tried everything from simple selects/joins to the dreaded cursors, but I am having trouble matching the "ups" to the corresponding "downs" and putting them in the temp table with the correct "run".
到目前为止,我已经尝试了从简单的选择/连接到可怕的游标的所有内容,但是我无法将“ups”与相应的“下降”匹配,并将它们放入临时表中并使用正确的“运行”。
Any ideas on the best way to accomplish this?
有关实现这一目标的最佳方法的任何想法?
EDIT:
Sample schema:
CREATE TABLE Run
([RunID] int, [PlayerID] int, [Score] int)
;
INSERT INTO Run
([RunID], [PlayerID], [Score])
VALUES
(1, 1, 1000),
(2, 1, 1100),
(3, 1, 800),
(4, 2, 1500),
(5, 1, 900)
;
CREATE TABLE Jump
([JumpID] int, [RunID] int, [Time] datetime, [Type] int)
;
INSERT INTO Jump
([JumpID], [RunID], [Time], [Type])
VALUES
(1, 1, '2013-08-13 18:00:04', 1),
(2, 1, '2013-08-13 18:00:10', 2),
(3, 2, '2013-08-13 18:02:15', 1),
(4, 2, '2013-08-13 18:02:45', 4),
(5, 3, '2013-08-13 18:04:20', 3),
(6, 3, '2013-08-13 18:05:01', 2),
(7, 4, '2013-08-13 18:10:12', 3),
(8, 4, '2013-08-13 18:11:25', 4),
(9, 5, '2013-08-13 18:15:00', 1),
(10, 5, '2013-08-13 18:25:20', 4)
;
CREATE TABLE JumpType
([TypeID] int, [Description] varchar(12))
;
INSERT INTO JumpType
([TypeID], [Description])
VALUES
(1, 'UpPlatform'),
(2, 'DownPlatform'),
(3, 'UpBoost'),
(4, 'DownBoost')
;
Expected output of the query would be a temp table similar to:
查询的预期输出将是类似于以下的临时表:
RunID PlayerID TimeUp TimeDown
1 1 '2013-08-13 18:00:04' 2013-08-13 18:00:10
4 个解决方案
#1
2
EDIT
Based on your updated question this will work. I've joined on your jump type table rather than assuming the id's (personally I think its a bad idea to assume id's eg assume 1 and 3 are the up type)
根据您更新的问题,这将有效。我加入了你的跳转类型表,而不是假设id(我个人认为假设id是一个坏主意,例如假设1和3是up类型)
Also I've used an inner join to get the corresponding down jump - I am assuming that if the jumper goes up he will come down ;)
另外我使用内部连接来获得相应的向下跳跃 - 我假设如果跳线上升他将会下降;)
select
r.RunID,
r.PlayerID,
TimeUp = uj.[Time],
TimeDown = dj.[Time],
TimeDifference = DATEDIFF(MILLISECOND, uj.Time, dj.Time)
from @Run r
inner join @Jump uj on uj.RunID = r.RunID
inner join @JumpType ut on ut.TypeID = uj.[Type]
inner join @Jump dj on dj.RunID = uj.RunID
inner join @JumpType dt on dt.TypeID = dj.[Type]
where ut.[Description] like '%Up%'
and dt.[Description] like '%Down%'
ORIGINAL - before you showed us your schema
ORIGINAL - 在向我们展示您的架构之前
Heres what I cam up with
继承人我所追求的是什么
The type table indicate if its an up or down time with the IsUpElseAssumeIsDown
field
类型表指示IsUpElseAssumeIsDown字段的上升或下降时间
declare @TimeType table (Id int, Name nvarchar(20), IsUpElseAssumeIsDown bit)
insert into @TimeType (Id, Name, IsUpElseAssumeIsDown) values
(1, '1st Up Type', 1), (2, '1st Down Type', 0),
(3, '2st Up Type', 1), (4, '2st Down Type', 0)
Now a set up jumps to test with
现在设置跳转到测试
declare @Jump table ([ID] int, [RunID] int, [Time] time, [Type] int)
insert into @Jump ([ID], [RunID], [Time], [Type]) values
(1, 1, '10:00:05.000', 1), (2, 1, '10:00:15.000', 2),
(3, 2, '10:00:15.000', 3), (4, 2, '10:00:25.100', 4),
(5, 3, '10:00:25.000', 1), (6, 3, '10:00:35.200', 4),
(7, 4, '10:00:35.000', 3), (8, 4, '10:00:45.300', 4),
(9, 5, '10:00:45.000', 1), -- no down time for 1st up type
(10, 6, '10:00:55.000', 3) -- no down time for 2nd up type
Finally a query to get our results
最后一个查询来获得我们的结果
-- @tempJump ([RunID], [TimeUp], [TimeDown])
;with UpJump
as
(
select j.RunID, j.[Time]
from @Jump j
inner join @TimeType t on t.Id = j.[Type]
where t.IsUpElseAssumeIsDown = 1
)
,DownJump
as
(
select j.RunID, j.[Time]
from @Jump j
inner join @TimeType t on t.Id = j.[Type]
where t.IsUpElseAssumeIsDown = 0
)
select
u.RunID,
TimeUp = u.[Time],
TimeDown = d.[Time],
TimeDifference = DATEDIFF(MILLISECOND, u.Time, d.Time)
from UpJump u
inner join DownJump d on d.RunID = u.RunID
Results in this
结果就是这样
RunID TimeUp TimeDown TimeDifference
1 10:00:05.0000000 10:00:15.0000000 10000
2 10:00:15.0000000 10:00:25.1000000 10100
3 10:00:25.0000000 10:00:35.2000000 10200
4 10:00:35.0000000 10:00:45.3000000 10300
I've used cte's to make the query more readable but you could have written like this (with just joins)
我用过cte来使查询更具可读性,但你可以像这样编写(只需加入)
select
uj.RunID,
TimeUp = uj.[Time],
TimeDown = dj.[Time],
TimeDifference = DATEDIFF(MILLISECOND, uj.Time, dj.Time)
from @Jump uj
inner join @TimeType ut on ut.Id = uj.[Type]
inner join @Jump dj on dj.RunID = uj.RunID
inner join @TimeType dt on dt.Id = dj.[Type]
where ut.IsUpElseAssumeIsDown = 1
and dt.IsUpElseAssumeIsDown = 0
#2
1
select
r.RunID, r.PlayerID, ju.Time as TimeUp, jd.Time as TimeDown
from Run as R
left outer join Jump as ju on ju.RunID = r.RunID and ju.[Type] in (1, 3)
left outer join Jump as jd on jd.RunID = r.RunID and jd.[Type] in (2, 4)
sql小提琴演示
#3
0
SELECT r.RunID, up.Time, down.Time, DATEDIFF(millisecond, up.Time, down.Time) as miliseconds
FROM Run r
LEFT JOIN Jump up ON r.RunID = up.RunID AND (up.Type = 1 OR up.Type = 3)
LEFT JOIN Jump down ON r.RunID = down.RunID AND (down.Type = 2 OR down.Type = 4)
WHERE up.JumpID IS NOT NULL AND down.JumpID IS NOT NULL
#4
0
select J.RunID,Max(R.PlayerID) as PlayerID,min(J.Time) as TimeUP,max(J.time) as TimeDown
from Run R
inner join Jump J on R.RunID=J.RunID
inner join JumpType JT on J.Type=JT.TypeID
where JT.Description in ('UpPlatform','DownPlatform')
or JT.Description in ('UpPlatform','DownPlatform')
group by J.RunID
having COUNT(J.RunID)>1
#1
2
EDIT
Based on your updated question this will work. I've joined on your jump type table rather than assuming the id's (personally I think its a bad idea to assume id's eg assume 1 and 3 are the up type)
根据您更新的问题,这将有效。我加入了你的跳转类型表,而不是假设id(我个人认为假设id是一个坏主意,例如假设1和3是up类型)
Also I've used an inner join to get the corresponding down jump - I am assuming that if the jumper goes up he will come down ;)
另外我使用内部连接来获得相应的向下跳跃 - 我假设如果跳线上升他将会下降;)
select
r.RunID,
r.PlayerID,
TimeUp = uj.[Time],
TimeDown = dj.[Time],
TimeDifference = DATEDIFF(MILLISECOND, uj.Time, dj.Time)
from @Run r
inner join @Jump uj on uj.RunID = r.RunID
inner join @JumpType ut on ut.TypeID = uj.[Type]
inner join @Jump dj on dj.RunID = uj.RunID
inner join @JumpType dt on dt.TypeID = dj.[Type]
where ut.[Description] like '%Up%'
and dt.[Description] like '%Down%'
ORIGINAL - before you showed us your schema
ORIGINAL - 在向我们展示您的架构之前
Heres what I cam up with
继承人我所追求的是什么
The type table indicate if its an up or down time with the IsUpElseAssumeIsDown
field
类型表指示IsUpElseAssumeIsDown字段的上升或下降时间
declare @TimeType table (Id int, Name nvarchar(20), IsUpElseAssumeIsDown bit)
insert into @TimeType (Id, Name, IsUpElseAssumeIsDown) values
(1, '1st Up Type', 1), (2, '1st Down Type', 0),
(3, '2st Up Type', 1), (4, '2st Down Type', 0)
Now a set up jumps to test with
现在设置跳转到测试
declare @Jump table ([ID] int, [RunID] int, [Time] time, [Type] int)
insert into @Jump ([ID], [RunID], [Time], [Type]) values
(1, 1, '10:00:05.000', 1), (2, 1, '10:00:15.000', 2),
(3, 2, '10:00:15.000', 3), (4, 2, '10:00:25.100', 4),
(5, 3, '10:00:25.000', 1), (6, 3, '10:00:35.200', 4),
(7, 4, '10:00:35.000', 3), (8, 4, '10:00:45.300', 4),
(9, 5, '10:00:45.000', 1), -- no down time for 1st up type
(10, 6, '10:00:55.000', 3) -- no down time for 2nd up type
Finally a query to get our results
最后一个查询来获得我们的结果
-- @tempJump ([RunID], [TimeUp], [TimeDown])
;with UpJump
as
(
select j.RunID, j.[Time]
from @Jump j
inner join @TimeType t on t.Id = j.[Type]
where t.IsUpElseAssumeIsDown = 1
)
,DownJump
as
(
select j.RunID, j.[Time]
from @Jump j
inner join @TimeType t on t.Id = j.[Type]
where t.IsUpElseAssumeIsDown = 0
)
select
u.RunID,
TimeUp = u.[Time],
TimeDown = d.[Time],
TimeDifference = DATEDIFF(MILLISECOND, u.Time, d.Time)
from UpJump u
inner join DownJump d on d.RunID = u.RunID
Results in this
结果就是这样
RunID TimeUp TimeDown TimeDifference
1 10:00:05.0000000 10:00:15.0000000 10000
2 10:00:15.0000000 10:00:25.1000000 10100
3 10:00:25.0000000 10:00:35.2000000 10200
4 10:00:35.0000000 10:00:45.3000000 10300
I've used cte's to make the query more readable but you could have written like this (with just joins)
我用过cte来使查询更具可读性,但你可以像这样编写(只需加入)
select
uj.RunID,
TimeUp = uj.[Time],
TimeDown = dj.[Time],
TimeDifference = DATEDIFF(MILLISECOND, uj.Time, dj.Time)
from @Jump uj
inner join @TimeType ut on ut.Id = uj.[Type]
inner join @Jump dj on dj.RunID = uj.RunID
inner join @TimeType dt on dt.Id = dj.[Type]
where ut.IsUpElseAssumeIsDown = 1
and dt.IsUpElseAssumeIsDown = 0
#2
1
select
r.RunID, r.PlayerID, ju.Time as TimeUp, jd.Time as TimeDown
from Run as R
left outer join Jump as ju on ju.RunID = r.RunID and ju.[Type] in (1, 3)
left outer join Jump as jd on jd.RunID = r.RunID and jd.[Type] in (2, 4)
sql小提琴演示
#3
0
SELECT r.RunID, up.Time, down.Time, DATEDIFF(millisecond, up.Time, down.Time) as miliseconds
FROM Run r
LEFT JOIN Jump up ON r.RunID = up.RunID AND (up.Type = 1 OR up.Type = 3)
LEFT JOIN Jump down ON r.RunID = down.RunID AND (down.Type = 2 OR down.Type = 4)
WHERE up.JumpID IS NOT NULL AND down.JumpID IS NOT NULL
#4
0
select J.RunID,Max(R.PlayerID) as PlayerID,min(J.Time) as TimeUP,max(J.time) as TimeDown
from Run R
inner join Jump J on R.RunID=J.RunID
inner join JumpType JT on J.Type=JT.TypeID
where JT.Description in ('UpPlatform','DownPlatform')
or JT.Description in ('UpPlatform','DownPlatform')
group by J.RunID
having COUNT(J.RunID)>1