Disons que j'ai le tableau suivant:
Value Time
0 15/06/2012 8:03:43 PM
1 15/06/2012 8:03:43 PM *
1 15/06/2012 8:03:48 PM
1 15/06/2012 8:03:53 PM
1 15/06/2012 8:03:58 PM
2 15/06/2012 8:04:03 PM *
2 15/06/2012 8:04:08 PM
3 15/06/2012 8:04:13 PM *
3 15/06/2012 8:04:18 PM
3 15/06/2012 8:04:23 PM
2 15/06/2012 8:04:28 PM *
2 15/06/2012 8:04:33 PM
Comment sélectionner les lignes suivies, c’est-à-dire où Value
a changé? En gros, j'essaie de trouver le moment où Value
a changé pour pouvoir effectuer d'autres requêtes en fonction de ces intervalles. La solution ne devrait pas dépendre de connaître Value
ou Time
à l'avance.
Il me semble que cela ne devrait pas être très difficile (mais c'est assez difficile pour moi apparemment!).
J'utilise actuellement SQL Server 2008 bien que j'aie accès à 2012 si les nouvelles fonctions de fenêtre/d'analyse sont utiles.
J'ai essayé d'adapter les solutions ici http://blog.sqlauthority.com/2011/11/24/sql-server-solution-to-puzzle-simulate-lead-and-lag-without-using-sql-server- 2012-analytic-function/ mais ma requête n'a pas abouti au bout d'une heure! Je pense que les jointures font exploser la taille de la ligne en quelque chose d'ingérable (ou je l'ai foiré).
Je peux résoudre ce problème avec du code C # et des appels multiples à la base de données, mais cela semble être une tâche qui pourrait être réalisée dans une fonction table-value ou SP, ce qui serait beaucoup plus agréable.
De plus, une solution qui ne fonctionne qu'avec une augmentation de Value
est acceptable si cela est plus facile.
Je pense que c'est ce que vous recherchez:
;WITH x AS
(
SELECT value, time, rn = ROW_NUMBER() OVER
(PARTITION BY Value ORDER BY Time)
FROM dbo.table
)
SELECT * FROM x WHERE rn = 1;
Cela peut être lent si le jeu de résultats est volumineux et s'il n'y a pas un bon index de support ...
MODIFIER
Ah, attendez une seconde, les valeurs montent et descendent, pas seulement vers le haut ... si c'est le cas, vous pouvez essayer cette approche beaucoup plus lente:
DECLARE @x TABLE(value INT, [time] DATETIME)
INSERT @x VALUES
(0,'20120615 8:03:43 PM'),--
(1,'20120615 8:03:43 PM'),--*
(1,'20120615 8:03:48 PM'),--
(1,'20120615 8:03:53 PM'),--
(1,'20120615 8:03:58 PM'),--
(2,'20120615 8:04:03 PM'),--*
(2,'20120615 8:04:08 PM'),--
(3,'20120615 8:04:13 PM'),--*
(3,'20120615 8:04:18 PM'),--
(3,'20120615 8:04:23 PM'),--
(2,'20120615 8:04:28 PM'),--*
(2,'20120615 8:04:33 PM');
;WITH x AS
(
SELECT *, rn = ROW_NUMBER() OVER (ORDER BY time)
FROM @x
)
SELECT x.value, x.[time]
FROM x LEFT OUTER JOIN x AS y
ON x.rn = y.rn + 1
AND x.value <> y.value
WHERE y.value IS NOT NULL;
Résultats:
value time
----- -----------------------
1 2012-06-15 20:03:43.000
2 2012-06-15 20:04:03.000
3 2012-06-15 20:04:13.000
2 2012-06-15 20:04:28.000
DECLARE @x TABLE(value INT, [time] DATETIME)
INSERT @x VALUES
(0,'20120615 8:03:43 PM'),--
(1,'20120615 8:03:43 PM'),--*
(1,'20120615 8:03:48 PM'),--
(1,'20120615 8:03:53 PM'),--
(1,'20120615 8:03:58 PM'),--
(2,'20120615 8:04:03 PM'),--*
(2,'20120615 8:04:08 PM'),--
(3,'20120615 8:04:13 PM'),--*
(3,'20120615 8:04:18 PM'),--
(3,'20120615 8:04:23 PM'),--
(2,'20120615 8:04:28 PM'),--*
(2,'20120615 8:04:33 PM');
; with temp as
(
SELECT
value, [time], lag(value,1,-1) over (order by [time] ) as lastValue
FROM @x
)
SELECT
[value],[time]
FROM
temp
WHERE value <> lastValue
Résultats:
value time
---------------------------
0 2012-06-15 20:03:43.000
1 2012-06-15 20:03:43.000
2 2012-06-15 20:04:03.000
3 2012-06-15 20:04:13.000
2 2012-06-15 20:04:28.000
Nous pouvons le faire en utilisant également des sous-requêtes
SELECT sub1.value, sub1.time FROM
(SELECT *,rn,id FROM
(SELECT *,row_number() over (partition by value order by time) AS rn, row_number() over (order by time) AS id FROM x ) order by time) sub1
LEFT OUTER JOIN
(SELECT *,rn,id FROM
(SELECT *,row_number() over (partition by value order by time) AS rn, row_number() over (order by time) AS id FROM x ) order by time) sub2
ON sub1.id = sub2.id + 1
WHERE sub1.rn - sub2.rn <> 1 OR sub2.rn IS NULL;
Donc, j'ai comparé les valeurs de 2 lignes si cela change, la différence de rn ne sera pas égale à 1, sinon la valeur de rn augmentera de 1; sub2.rn IS NULL est utilisé pour la première ligne car la jointure aura lieu à partir de id = 2.