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

Langage SQL Discussion :

Requête SQL excluant des périodes


Sujet :

Langage SQL

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 551
    Points : 264
    Points
    264
    Par défaut Requête SQL excluant des périodes
    Bonjour,

    J'ai besoin de récupérer tous les utilsateurs DISTINCT en excluant ceux qui ne sont pas disponibles en fonction de périodes de temps.

    Table user:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    +------+-----------+--------------------------------------+
    | id   | firstname | content                              |
    +------+-----------+--------------------------------------+
    | 13   | John      | ...                                  |
    | 44   | Marc      | ...                                  |
    | 55   | Elise     | ...                                  |
    +------+-----------+--------------------------------------+
    Table unavailability:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    +------+-----------+--------------+--------------+
    | id   | user_id   | start        | end          |
    +------+-----------+--------------+--------------+
    | 1    | 13        | 2019-07-01   | 2019-07-10   |
    | 2    | 13        | 2019-07-20   | 2019-07-30   |
    | 3    | 13        | 2019-09-01   | 2019-09-30   |
    | 4    | 44        | 2019-08-01   | 2019-08-15   |
    +------+-----------+--------------+--------------|

    Par exemple, nous voulons récupérer les utilsateurs qui ne sont disponibles entre les dates 2019-06-20 / 2019-07-05: Marc et Elise sont dispos.

    Est-ce que l'on peut utiliser un LEFT JOIN? Cette requête ne fonctionne pas:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT DISTINCT user.*, unavailability.start, unavailability.end,
    FROM user
    LEFT JOIN unavailability ON unavailability.user_id = user.id
    WHERE  
    unavailability.start < "2019-06-20" AND unavailability.end > "2019-06-20"
    AND unavailability.start < "2019-07-05" AND unavailability.end > "2019-07-05"
    Merci pour votre aide,
    Vincent.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 240
    Points : 12 872
    Points
    12 872
    Par défaut
    Bonjour,
    Avec un LEFT OUTER JOIN, les critères sur la table de droite doivent être dans la jointure, sinon celle-ci se "transforme" en jointure interne.
    Par exemple ici la requête doit être écrite ainsi:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT DISTINCT user.*, unavailability.start, unavailability.end,
    FROM user
    LEFT JOIN unavailability ON unavailability.user_id = user.id
    and unavailability.start < "2019-06-20" AND unavailability.start < "2019-07-05" AND unavailability.end > "2019-07-05" AND unavailability.end > "2019-06-20"
    J'en ai profité pour regrouper les critères sur les colonnes start et end, ce qui met en lumière une grosse incohérence…

    Maintenant pour en revenir au besoin initial, Il faut chercher les lignes de user pour lesquelles il n'existe pas de ligne dans unavailability avec les bonnes dates.
    On peut partir de cette requête, ou utiliser un NOT EXISTS.

    Tatayo.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    776
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 776
    Points : 1 488
    Points
    1 488
    Par défaut
    Bonjour Vincent,

    Le fait de faire une conditionnelle sur la table "externe" inhibe l'effet de l'outer join.
    En clair, c'est ce que tu fais.

    Selon le SGBD, on peut "remonter" la conditionnelle dans la clause ON de la jointure.

    Sinon on peut passer par une sous requête.
    Encore une fois selon ton SGBD on peut écrire ça de manière plus ou moins élégante (= maintenable)

    La façon la plus "tout terrain" (et donc pleine de tâches ) donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT DISTINCT user.*, U.start, U.end
    FROM user
    	LEFT JOIN	(SELECT User_id, start, end
    			FROM  unavailability 
    			WHERE  start < "2019-06-20" AND end > "2019-07-05"
    			) U ON U.user_id = user.id
    Au passage, si start < "2019-06-20" alors start < "2019-07-05" et inversement pour end

    Quel est ton SGBD ?

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 551
    Points : 264
    Points
    264
    Par défaut
    Oui super ça marche!

    Mon SGBD est MySQL.

    Merci

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 551
    Points : 264
    Points
    264
    Par défaut
    Entre temps j'ai découvert db-fiddle.com ! Top pour faire des tests je trouve:

    https://www.db-fiddle.com/f/2jVY7tT8bPXJLtrcz44CKR/0

  6. #6
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    776
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 776
    Points : 1 488
    Points
    1 488
    Par défaut
    Merci du retour et bonne nouvelle

    Quelle version de Mysql ?

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 551
    Points : 264
    Points
    264
    Par défaut
    La version de MySQL en PROD est 5.7.
    En dev local je suis sous MariaDB en version 10.1.38

    C'est peut-être pas très judicieux de ma part !!!

  8. #8
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    776
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 776
    Points : 1 488
    Points
    1 488
    Par défaut
    Re,

    Disons que les CTE (with) et les fonctions de fenêtrage (OVER) sont de grandes avancées.
    Elles ne sont dispo qu'à partir de Mysql 8.0 et MariaDB 10.2

    Au vu du prix de la licence, il est judicieux de réfléchir régulièrement à une migration vers une version stable et fonctionnelle

    @+

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 26/07/2009, 10h06
  2. [Requête/SQL]Importer des données d'une table à l'autre
    Par atlantideD dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 18/04/2007, 10h46
  3. [MySQL] Introduire une variable dans requête SQL, insérer des données à la volée
    Par Ronan.f dans le forum PHP & Base de données
    Réponses: 18
    Dernier message: 29/04/2006, 22h10
  4. [SQL2K] requête SQL, comparer des dates
    Par cortex024 dans le forum MS SQL Server
    Réponses: 10
    Dernier message: 16/03/2006, 14h32
  5. [VB.NET] [SQL] Pb requête sql, récupérer des params. ?
    Par Pleymo dans le forum Windows Forms
    Réponses: 3
    Dernier message: 03/02/2005, 20h15

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