IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MS SQL Server Discussion :

Requête récursive (For Loop) [2008]


Sujet :

MS SQL Server

  1. #1
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Par défaut Requête récursive (For Loop)
    Bonjour,

    Je suis débutante avec Sql Server et j'aurais une petite question à vous poser :
    J'ai les données suivante :
    ID Type DateDébut DateFin
    1 A 01/01/2012 31/01/2012
    1 B 01/02/2012 31/03/2013
    1 C 05/04/2013 31/04/2013
    2 0A 01/01/2010 31/01/2011
    2 F 01/01/2013 31/01/2013

    Je souhaite pour chaque ID récupèrer la date de début la plus petite si la différence entre date de fin de Type et DateDébut de prochain type <30 jours. Je m'explique, pour l'ID 1 date début pour Type A=01/01/2012 et date fin 31/01/2012
    pour le type suiavnt B date de début de B-DateFin de A est <30 donc on garde toujours DateDébut=01/01/2012 jusqu'à ce qu"on fini l'itération sur tout les type pour ID=1.
    Pour ID 2 par exple dateFin de type 0A et dateDébut de prochain type (F) est > 30 donc on ne garde pas 01/01/2010 mais le 01/01/2013.

    Je pensais me baser sur les for loop mais je ne m'en sors pas trop bien.
    N'hésitez pas si vous avez des questions ou si je n'étais pas assez claire.

    Merci d'avance,
    Cordialement

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Bonjour,

    Sur quel critère vous appuyez-vous pour ordonner les types ? leur date de création ?

    Pouvez vous donner le résultat (complet) attendu par rapport aux données que vous avez présentées ?

  3. #3
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    Sur quel critère vous appuyez-vous pour ordonner les types ? leur date de création ?

    Pouvez vous donner le résultat (complet) attendu par rapport aux données que vous avez présentées ?
    Merci pour votre réponse.
    Non je n'ai pas de critère sur le type mon seul critère c'est l'ordre des dates.
    pour mon exemple ci-dessous:
    ID Type DateDébut DateFin
    1 A 01/01/2012 31/01/2012
    1 B 01/02/2012 31/03/2013
    1 C 05/04/2013 31/04/2013
    2 0A 01/01/2010 31/01/2011
    2 F 01/01/2013 31/01/2013

    Les résultats attendus sont :

    ID DateDébut
    1 01/01/2012
    2 01/01/2013

    Merci.

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    De ce que j'en comprend, le problème pourrait être reformulé ainsi :

    Quel est, pour chaque ID, la date de début la plus grande X pour laquelle il n'existe pas d'autre ligne ayant le même ID et une date de fin de moins de 30 jours avant X

    Ce qui se traduit en SQL par (par exemple)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT	ID, MAX(datedebut) as DateDebut
    FROM	LaTable P
    WHERE	NOT EXISTS (
    	SELECT 1
    	FROM LaTable S
    	WHERE P.ID = S.ID
    		AND	S.DateFin < P.DateDebut
    		AND DATEDIFF(DAY, S.DateFin, P.DateDebut) < 30
    	)
    GROUP BY ID

  5. #5
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    De ce que j'en comprend, le problème pourrait être reformulé ainsi :

    Quel est, pour chaque ID, la date de début la plus grande X pour laquelle il n'existe pas d'autre ligne ayant le même ID et une date de fin de moins de 30 jours avant X

    Ce qui se traduit en SQL par (par exemple)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT	ID, MAX(datedebut) as DateDebut
    FROM	LaTable P
    WHERE	NOT EXISTS (
    	SELECT 1
    	FROM LaTable S
    	WHERE P.ID = S.ID
    		AND	S.DateFin < P.DateDebut
    		AND DATEDIFF(DAY, S.DateFin, P.DateDebut) < 30
    	)
    GROUP BY ID


    C'est plutôt la date min dont j'ai besoin donc : la date de début la plus petite de X pour laquelle il n'existe pas d'autre ligne ayant le même ID et que la date de fin l'ID (correspond à X) et date début de même ID pour un autre type différente est < 30 jours . sachant que ID et Type sont dans la même table donc on n'a pas de table S et P (deux tables différentes) c'est pourquoi j'ai pensé à une solution récursive.

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Citation Envoyé par moiamal Voir le message
    C'est plutôt la date min dont j'ai besoin donc : la date de début la plus petite de X pour laquelle il n'existe pas d'autre ligne ayant le même ID et que la date de fin l'ID (correspond à X) et date début de même ID pour un autre type différente est < 30 jours .

    Dans ce cas, avec votre exemple, pour l'ID 2, la date devrait être 01/01/2010 et non 01/01/2013

    Citation Envoyé par moiamal Voir le message
    sachant que ID et Type sont dans la même table donc on n'a pas de table S et P (deux tables différentes) c'est pourquoi j'ai pensé à une solution récursive.
    Dans la requête que je vous ai données, S et P sont simplement des alias de la table, que j'ai arbitrairement appelée "LaTable".

    Je reste persuadé qu'une récursive n'est pas nécessaire dans votre cas...

  7. #7
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Dans ce cas, avec votre exemple, pour l'ID 2, la date devrait être 01/01/2010 et non 01/01/2013



    Dans la requête que je vous ai données, S et P sont simplement des alias de la table, que j'ai arbitrairement appelée "LaTable".

    Je reste persuadé qu'une récursive n'est pas nécessaire dans votre cas...

    Dans ID2 justement la différence entre date fin 31/01/2011 de Type 0A et la date début suivante de Type F est > à 30 donc on garde le dernier 01/01/2013

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Citation Envoyé par moiamal Voir le message
    donc on garde le dernier 01/01/2013
    Le dernier ! donc... la date la plus grande... donc... la date MAX !
    ou alors j'ai raté quelque chose

  9. #9
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Le dernier ! donc... la date la plus grande... donc... la date MAX !
    ou alors j'ai raté quelque chose
    ^_^ je pense que je n'étais pas assez claire, pardon
    Reprenons l'exemple de ID2 :
    ID Type DateDébut DateFin
    2 0A 01/01/2010 31/01/2011
    2 F 01/01/2013 31/01/2013

    Diffdate entre 31/01/2011 et 01/01/2013 > 30 donc en prends 01/01/2013 et supposons que ID 2 a ces infos:

    ID Type DateDébut DateFin
    2 0A 01/01/2010 31/01/2011
    2 F 01/01/2013 31/01/2013
    2 D 03/02/2013 31/04/2013
    2 G 01/05/2013 31/06/2014

    Dans ce cas on gardera notre date= 01/01/2013 car c'est elle la Min où la différence est < 30.

  10. #10
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Je persiste et signe, c'est bien la date max pour laquelle il n'y a pas de "trou" de plus de 30 jours après ! la date min, c'est (et restera) 01/01/2010.

    Avez-vous testé ma requête ?

    Elle ressort pourtant un résultat conforme a votre attente avec votre jeu d'essai, même après ajout de ces deux lignes pour l'ID 2 (et après modification des dates 31 avril par 30 avril, et 31 juin par 30 juin ):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    SET DATEFORMAT dmy
     
    CREATE TABLE laTable(
    	ID int
    	, type varchar(50)
    	, dateDebut datetime
    	, datefin datetime
    )
     
    INSERT INTO LaTable VALUES
    (1, 'A' , '01-01-2012', '31-01-2012')
    ,(1, 'B' , '01-02-2012', '31-03-2013')
    ,(1, 'C' , '05-04-2013', '30-04-2013')
    ,(2, '0A', '01-01-2010', '31-01-2011')
    ,(2, 'F' , '01-01-2013', '30-01-2013')
    ,(2, 'D' , '03/02/2013', '30/04/2013')
    ,(2, 'G' , '01/05/2013', '30/06/2014')
     
     
     
    SELECT	ID, MAX(datedebut) as DateDebut
    FROM	LaTable P
    WHERE	NOT EXISTS (
    	SELECT 1
    	FROM LaTable S
    	WHERE P.ID = S.ID
    		AND	S.DateFin < P.DateDebut
    		AND DATEDIFF(DAY, S.DateFin, P.DateDebut) < 30
    	)
    GROUP BY ID
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    1	2012-01-01 00:00:00.000
    2	2013-01-01 00:00:00.000

  11. #11
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    je crois savoir d’où vient la confusion MIN/MAX depuis le début.

    Reformulé encore autrement, vous cherchez :
    La date de début de la dernière période, pour chaque ID. Où par période, on entend un ensemble de lignes dont les dates se suivent et pour lesquelles il n'y a pas d’écart de plus de trente jour entre la date de début et la date de fin (de la ligne précédente).

    Votre MIN concerne le fait de récupérer la première date de début de la cette période
    Mon MAX concerne le fait de récupérer la dernière période.

    Comme tout ce qui nous intéresse est de trouver le début de la période, on peut trouver tous les débuts de période par le fait qu'il n'existe pas d'autre ligne dont la date de fin est à moins de trente jours. En faisant ainsi, j'élimine "votre MIN" (et j'obtiens donc toutes les lignes qui représentent un début de "période", et seulement elles) : c'est le but du NOT EXISTS.

    Enfin, je regroupe par ID, et je ne garde que le MAX des "date de début des périodes", pour obtenir la date de début de la dernière période.

    Est-ce plus clair, et surtout est-ce bien ce que vous voulez ?

  12. #12
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    je crois savoir d’où vient la confusion MIN/MAX depuis le début.

    Reformulé encore autrement, vous cherchez :
    La date de début de la dernière période, pour chaque ID. Où par période, on entend un ensemble de lignes dont les dates se suivent et pour lesquelles il n'y a pas d’écart de plus de trente jour entre la date de début et la date de fin (de la ligne précédente).

    Votre MIN concerne le fait de récupérer la première date de début de la cette période
    Mon MAX concerne le fait de récupérer la dernière période.

    Comme tout ce qui nous intéresse est de trouver le début de la période, on peut trouver tous les débuts de période par le fait qu'il n'existe pas d'autre ligne dont la date de fin est à moins de trente jours. En faisant ainsi, j'élimine "votre MIN" (et j'obtiens donc toutes les lignes qui représentent un début de "période", et seulement elles) : c'est le but du NOT EXISTS.

    Enfin, je regroupe par ID, et je ne garde que le MAX des "date de début des périodes", pour obtenir la date de début de la dernière période.

    Est-ce plus clair, et surtout est-ce bien ce que vous voulez ?


    Bonjour
    Oui c'est très clair maintenant et la solution fonctionnent parfaitement et moins compliqué que les fetch que je cherchais
    Merci beaucoup

    Cordialement

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Requête récursive dans access
    Par Australia dans le forum Requêtes et SQL.
    Réponses: 15
    Dernier message: 29/07/2014, 15h15
  2. [SQL Server]Problème avec une requête récursive
    Par evans dans le forum Langage SQL
    Réponses: 3
    Dernier message: 05/04/2006, 20h16
  3. [SQL Server] Requête récursive
    Par margagn dans le forum Langage SQL
    Réponses: 8
    Dernier message: 01/04/2006, 04h31
  4. Erreur "For loop variable simple local varaible"
    Par Yepazix dans le forum Langage
    Réponses: 13
    Dernier message: 17/09/2005, 22h09
  5. Requête récursive
    Par tirixil dans le forum Bases de données
    Réponses: 3
    Dernier message: 07/03/2005, 16h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo