October 4, 2011 at 7:46 am
Hi,
I have a table:
CREATE TABLE Test
(
Index INT,
Value INT,
Stamp DATETIME
)
Data from the table:
Index Value Stamp
=====================================
1 1 2007-08-03 08:00:00.000
2 1 2007-08-05 08:00:00.000
3 3 2007-08-11 08:00:00.000
4 3 2007-08-16 08:00:00.000
5 3 2007-08-19 08:00:00.000
6 1 2007-08-23 08:00:00.000
7 1 2007-08-25 08:00:00.000
8 4 2007-08-29 08:00:00.000
9 3 2007-08-33 08:00:00.000
10 3 2007-08-37 08:00:00.000
I need a query that get how long last a value:
Values Start End
==========================================================
1 2007-08-03 08:00:00.000 2007-08-05 08:00:00.000
3 2007-08-11 08:00:00.000 2007-08-19 08:00:00.000
1 2007-08-23 08:00:00.000 2007-08-25 08:00:00.000
4 2007-08-29 08:00:00.000 2007-08-29 08:00:00.000
3 2007-08-33 08:00:00.000 2007-08-37 08:00:00.000
Thanks,
ioani
October 4, 2011 at 9:15 am
This was removed by the editor as SPAM
October 4, 2011 at 9:17 am
It's an "island" problem.
Try this:
--setup
DECLARE @test-2 TABLE
(
[Index] INT,
[Value] INT,
[Stamp] DATETIME
)
INSERT INTO @test-2 VALUES (1, 1, '2007-08-03 08:00:00.000');
INSERT INTO @test-2 VALUES (2, 1, '2007-08-05 08:00:00.000');
INSERT INTO @test-2 VALUES (3, 3, '2007-08-11 08:00:00.000');
INSERT INTO @test-2 VALUES (4, 3, '2007-08-16 08:00:00.000');
INSERT INTO @test-2 VALUES (5, 3, '2007-08-19 08:00:00.000');
INSERT INTO @test-2 VALUES (6, 1, '2007-08-23 08:00:00.000');
INSERT INTO @test-2 VALUES (7, 1, '2007-08-25 08:00:00.000');
INSERT INTO @test-2 VALUES (8, 4, '2007-08-29 08:00:00.000');
INSERT INTO @test-2 VALUES (9, 3, '2007-08-30 08:00:00.000');
INSERT INTO @test-2 VALUES (10, 3, '2007-08-31 08:00:00.000');
--solution
WITH IslandData AS (
SELECT *,
Island_id = ROW_NUMBER() OVER (ORDER BY Stamp) -
ROW_NUMBER() OVER (PARTITION BY Value ORDER BY Stamp)
FROM @test-2
),
RankedData AS (
SELECT *,
RankInIsland = ROW_NUMBER() OVER (PARTITION BY island_id ORDER BY Stamp),
ReverseRankInIsland = ROW_NUMBER() OVER (PARTITION BY island_id ORDER BY Stamp DESC)
FROM IslandData
)
SELECT A.Value, A.Stamp AS Start, B.Stamp AS [End]
FROM RankedData AS A
INNER JOIN RankedData AS B
ON A.island_id = B.island_id
AND B.ReverseRankInIsland = 1
WHERE A.RankInIsland = 1
ORDER BY A.Stamp
BTW, your sample data looks wrong (does August have 37 days?).
-- Gianluca Sartori
October 4, 2011 at 9:20 am
WITH CTE AS (
SELECT [Index],Value,Stamp,
ROW_NUMBER() OVER(ORDER BY [Index])AS rn1,
ROW_NUMBER() OVER(PARTITION BY Value ORDER BY [Index])AS rn2
FROM Test)
SELECT Value,MIN(Stamp) AS Start, MAX(Stamp) AS [End]
FROM CTE
GROUP BY Value,rn1-rn2
ORDER BY MIN(Stamp);
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537October 4, 2011 at 9:48 am
Mark-101232 (10/4/2011)
WITH CTE AS (
SELECT [Index],Value,Stamp,
ROW_NUMBER() OVER(ORDER BY [Index])AS rn1,
ROW_NUMBER() OVER(PARTITION BY Value ORDER BY [Index])AS rn2
FROM Test)
SELECT Value,MIN(Stamp) AS Start, MAX(Stamp) AS [End]
FROM CTE
GROUP BY Value,rn1-rn2
ORDER BY MIN(Stamp);
Ah! I knew I was missing something!
Thank you very much, Mark!
-- Gianluca Sartori
October 5, 2011 at 12:23 am
Sorry, for putting wrong sample data. The data should be between 1 and 31 August.
October 5, 2011 at 12:24 am
Thank you,
Very nice solution.
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply