2011-07-08 2 views
4

Je n'arrive pas à trouver comment démarrer cette requête.rechercher des enregistrements pour un utilisateur qui n'est pas contigu

J'ai une table qui a les colonnes suivantes et les données:

User BeginMile EndMile 
1   1  5 
1   5  6 
1   6  20 
1   20  25 
1   25  29 
2   1   9 
2   15  20 
3   1   2 
3   6   10 
3   10  12 

je dois d'abord trouver où il y a des lacunes pour chaque utilisateur du EndMile du précédent record, à la BeginMile de l'enregistrement suivant . J'ai ensuite besoin de retourner l'enregistrement avant et après où l'écart se produit pour chaque utilisateur.

Dans l'exemple de données précédente, je voudrais le texte suivant retourné:

User PrevBeginMile PrevEndMile AfterBeginMile AfterEndMile Gap 
2   1    9    15   20   6 
3   1    2    6   10   4 

Comment cela peut-il être fait?

+3

Quelle base de données utilisez-vous? –

+0

BeginDate et EndDate? Voulez-vous dire BeginMile et EndMile? –

+0

J'utilise SQL 2005 – mameesh

Répondre

3

Considérant que vous êtes sur SQL 2005, cela devrait fonctionner:

DECLARE @Runners TABLE (Id INT, BeginMile INT, EndMile INT) 

INSERT INTO @Runners VALUES (1,1,5) 
INSERT INTO @Runners VALUES (1,5,6) 
INSERT INTO @Runners VALUES (1,6,20) 
INSERT INTO @Runners VALUES (1,20,25) 
INSERT INTO @Runners VALUES (1,25,29) 
INSERT INTO @Runners VALUES (2,1,9) 
INSERT INTO @Runners VALUES (2,15,20) 
INSERT INTO @Runners VALUES (3,1,2) 
INSERT INTO @Runners VALUES (3,6,10) 
INSERT INTO @Runners VALUES (3,10,12) 

WITH OrderedUsers AS (
    SELECT * 
    , ROW_NUMBER() OVER (PARTITION BY Id ORDER BY BeginMile) RowNum 
    FROM @Runners 
) 

SELECT a.Id [User] 
, a.BeginMile PrevBeginMile 
, a.EndMile PrevEndMile 
, b.BeginMile AfterBeginMile 
, b.EndMile AfterEndMile 
, b.BeginMile - a.EndMile Gap 
FROM OrderedUsers a 
JOIN OrderedUsers b 
ON a.Id = b.Id 
AND a.EndMile <> b.BeginMile 
AND a.RowNum = b.RowNum - 1 
+1

Je remplacerais les deux sous-requêtes par un CTE ... '; WITH ordered_table AS () SELECT blah DE ordered_table COMME INNER JOIN ordered_table AS b ON blah- de-blah' – MatBailie

+0

@Dems - Bonne suggestion. Actualisé. –

0

autres que l'utilisation RowNumber() [comme dans d'autres réponses], vous pouvez utiliser ...

SELECT 
    [current].User, 
    [current].BeginMile     AS [PrevBeginMile], 
    [current].EndMile      AS [PrevEndMile], 
    [next].BeginMile      AS [AfterBeginMile], 
    [next].EndMile      AS [AfterEndMile], 
    [next].BeginMile - [current].EndMile AS [Gap] 
FROM 
    myTable AS [current] 
CROSS APPLY 
    (SELECT TOP 1 * FROM myTable WHERE user = [current].User AND BeginMile > [current].BeginMile ORDER BY BeginMile ASC) AS [next] 
WHERE 
[current].EndMile <> [next].BeginMile 

Ou peut-être ...

FROM 
    myTable AS [current] 
INNER JOIN 
    myTable AS [next] 
    ON [next].BeginMile != [current].EndMile 
    AND [next].BeginMile = (
          SELECT 
           MIN(BeginMile) 
          FROM 
           myTable 
          WHERE 
           user = [current].User 
           AND BeginMile > [current].BeginMile 
          ) 
0

Que diriez-vous

WITH acte(user,beginmile,endmile) AS 
(
SELECT user,start,end 
ROW_NUMBER() OVER(PARTITION BY user ORDER BY START ASC) rownum 
FROM mytable 
) 
SELECT base.user,base.beginmile,base.endmile,base.BeginMile - lead.EndMile Gap 
FROM acte base 
LEFT JOIN acte lead on base.id=lead.id AND base.rownum=lead.rownum-1 
WHERE base.BeginMile - lead.EndMile > 0 
Questions connexes