これはギャップと諸島の問題として知られています。
島を特定するには、2つの順位付け関数を使用する必要があります。最初にセット内の行の位置を検索し、次にそのサブセット内の行の位置を見つける2番目の行(Line、Trip)、Soあなたがで終わるでしょう:あなたは
|Line |Trip |Speed |Timestamp R1 R2 (R1 - R2)
=======================================================================================
|100 |1 |50 kmh |2017-06-12 22:34:50 1 1 0
|100 |1 |55 kmh |2017-06-12 22:36:44 2 2 0
|100 |1 |56 kmh |2017-06-12 22:37:12 3 3 0
|200 |5 |12 kmh |2017-06-12 22:40:11 4 1 3
|200 |5 |18 kmh |2017-06-12 22:43:13 5 2 3
|100 |1 |23 kmh |2017-06-12 22:49:11 6 4 2
|100 |1 |45 kmh |2017-06-12 22:53:49 7 5 2
最後に各島の一意の識別子を取得し、他のから1を差し引く場合は、今すぐ
SELECT Line,
Trip,
Speed,
Timestamp,
R1 = ROW_NUMBER() OVER(ORDER BY Timestamp),
R2 = ROW_NUMBER() OVER(PARTITION BY Line, Trip ORDER BY Timestamp)
FROM dbo.YourTable;
|Line |Trip |Speed |Timestamp R1 R2
==========================================================================
|100 |1 |50 kmh |2017-06-12 22:34:50 1 1
|100 |1 |55 kmh |2017-06-12 22:36:44 2 2
|100 |1 |56 kmh |2017-06-12 22:37:12 3 3
|200 |5 |12 kmh |2017-06-12 22:40:11 4 1 <-- starts new sequence for new group
|200 |5 |18 kmh |2017-06-12 22:43:13 5 2
|100 |1 |23 kmh |2017-06-12 22:49:11 6 4 <-- follows on from where it left off
|100 |1 |45 kmh |2017-06-12 22:53:49 7 5
、あなたは開始時間を取得するには、この一意の識別子を使用することができますグループごとに:
SELECT Line,
Trip,
Speed,
Timestamp,
GroupStart = MIN(Timestamp) OVER(PARTITION BY Line, Trip, IslandID)
FROM ( SELECT Line,
Trip,
Speed,
Timestamp,
IslandID = ROW_NUMBER() OVER(ORDER BY Timestamp) -
ROW_NUMBER() OVER(PARTITION BY Line, Trip
ORDER BY Timestamp)
FROM dbo.YourTable
) AS t;
最後に、グループの開始時刻にDENSE_RANK()
を適用すると、整数のランキングが得られます。だからあなたのサンプルデータであなたが得るでしょう:
最初の3行のための
-- SAMPLE DATA
DECLARE @T TABLE (Line INT, Trip INT, Speed VARCHAR(6), Timestamp DATETIME);
INSERT @T (Line, Trip, Speed, Timestamp)
VALUES
(100, 1, '50 kmh', '2017-06-12 22:34:50'),
(100, 1, '55 kmh', '2017-06-12 22:36:44'),
(100, 1, '56 kmh', '2017-06-12 22:37:12'),
(200, 5, '12 kmh', '2017-06-12 22:40:11'),
(200, 5, '18 kmh', '2017-06-12 22:43:13'),
(100, 1, '23 kmh', '2017-06-12 22:49:11'),
(100, 1, '45 kmh', '2017-06-12 22:53:49');
WITH GroupedData AS
( SELECT Line,
Trip,
Speed,
Timestamp,
GroupStart = MIN(Timestamp) OVER(PARTITION BY Line, Trip, IslandID),
IslandID
FROM ( SELECT Line,
Trip,
Speed,
Timestamp,
IslandID = ROW_NUMBER() OVER(ORDER BY Timestamp) -
ROW_NUMBER() OVER(PARTITION BY Line, Trip
ORDER BY Timestamp)
FROM @T
) AS t
)
SELECT Line,
Trip,
Speed,
Timestamp,
GroupNumber = DENSE_RANK() OVER(ORDER BY GroupStart, IslandID)
FROM GroupedData
ORDER BY Timestamp;
OUTPUT
Line Trip Speed Timestamp GroupNumber
--------------------------------------------------------------
100 1 50 kmh 2017-06-12 22:34:50.000 1
100 1 55 kmh 2017-06-12 22:36:44.000 1
100 1 56 kmh 2017-06-12 22:37:12.000 1
200 5 12 kmh 2017-06-12 22:40:11.000 2
200 5 18 kmh 2017-06-12 22:43:13.000 2
100 1 23 kmh 2017-06-12 22:49:11.000 3
100 1 45 kmh 2017-06-12 22:53:49.000 3
(R1-R2)は0ではない1である(ただし、明らかにこれはの正しさを変更しません。答え) – etsa
@etsaありがとう。私はそれを訂正し、そのような基本的な算術的なエラーで私の頭を恥でぶら下げました – GarethD
これは完璧です。実際には、DENSE_RANKの余分な部分は必要ありません。最初のROW_NUMBERからROW_NUMBERを差し引くと、私のグループが完全に識別され、それだけで十分です。どうもありがとうございました! – Chris