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

Développement SQL Server Discussion :

Multi requêtes SQL à simplifier


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut Multi requêtes SQL à simplifier
    Bonjour,
    Je souhaiterais simplifier/optimiser mon code VB.NET qui fait des tests sur des données en BD SQL.

    J'ai une table, contenant un historique de valeurs (un record = une date avec une valeur numérique).
    J'ai besoin de savoir si ma valeur est par exemple : > 100 DEPUIS une date t.

    Donc pour le moment j'exécute 2 requêtes :
    - la 1ère retourne s'il existe ou non des records depuis x jours, avec valeur > 100
    - la 2ème retourne s'il existe ou non des records depuis x jours, avec valeur <= 100

    Ma fonction retourne VRAI si et seulement si la 1ère requête retourne un record, et la 2ème n'en retourne aucun.
    Ma question est donc : peut-on obtenir directement le résultat vrai/faux par requête ? (je voudrais éviter les EXIST/NOT EXIST trop lourds...)
    De plus, si il n'existe vraiment aucun record sur la période donnée, il me faut vérifier si le dernier record existant était bien > 100, dans ce cas je dois également retourner VRAI.

    Par avance merci pour votre aide et bonne journée !

  2. #2
    Invité
    Invité(e)
    Par défaut
    Oui c'est possible.
    Et en quoi les EXISTS c'est « trop lourd » ?

  3. #3
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Les exists seront vraisemblablement ce qu'il y a de plus léger.

    En revanche, ce qui est lent, c'est de faire plusieurs requêtes, donc s'il y a moyen d'avoir toutes les réponses en une seule requête, c'est ce qui sera le plus rapide, même si la requête est complexe.
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 138
    Points : 1 918
    Points
    1 918
    Par défaut
    Bonjour,

    Tu peux certainement tout faire en une seule requête. Il faudrait que tu nous donnes un jeu de données avec le résultat attendu.

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Oui quand je dis "lourd" je parle des imbrications de select à relire, surtout que dans mon exemple je ne parle pas des Where multiples qu'il faudra inclure.
    En tout cas merci de vos réponses.

    Citation Envoyé par StringBuilder Voir le message
    Bonjour,

    Les exists seront vraisemblablement ce qu'il y a de plus léger.

    En revanche, ce qui est lent, c'est de faire plusieurs requêtes, donc s'il y a moyen d'avoir toutes les réponses en une seule requête, c'est ce qui sera le plus rapide, même si la requête est complexe.

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Merci pour ta réponse,

    Voici un exemple :

    Clé 1 Clé 2 Clé 3 Date Valeur
    12 15 17 01/01/2021 100
    14 12 13 02/01/2021 200
    12 15 17 03/01/2021 700
    12 15 17 04/01/2021 300
    12 15 17 05/01/2021 400
    12 15 17 06/01/2021 500

    Pour la clé 12-15-17 :
    • "Est-ce que la valeur est < 600 depuis 3 jours --> la réponse doit être "OUI"
    • "Est-ce que la valeur est < 600 depuis 4 jours --> la réponse doit être "NON"


    Pour la clause "Depuis 3 jours" les requêtes utilisées sont :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT DATE, VALEUR FROM TABLE
    WHERE CLE1 = 12 AND CLE2 = 15 AND CLE3 = 17
    AND VALEUR < 600
    AND DATE >= DATEADD (DAY, -3, GETDATE())
     
    SELECT DATE, VALEUR FROM TABLE
    WHERE CLE1 = 12 AND CLE2 = 15 AND CLE3 = 17
    AND VALEUR >= 600
    AND DATE >= DATEADD (DAY, -3, GETDATE())
    Si la req 1 renvoie des résultats et la 2ème aucun --> résultat = OUI
    Sinon NON


    Par contre il se peut qu'il y ait des trous dans les dates, et qu'il n'existe aucun enregistrement pour les 3 derniers jours :

    Clé 1 Clé 2 Clé 3 Date Valeur
    12 15 17 01/12/2020 100
    14 12 13 02/12/2020 200
    12 15 17 13/12/2020 700
    12 15 17 24/12/2020 300
    12 15 17 01/01/2021 400
    12 15 17 02/01/2021 500

    Dans ce cas, il faut regarder la dernière valeur existante (pour la clé), et la comparer à 600 --> donc la réponse est "OUI"
    Tout ceci, je l'ai fait avec des requêtes multiples et avec des If...Else dans mon code, pas très joli...

    Est-ce faisable avec une requête unique ?



    Edit :
    Voici une requête unique mais incomplète :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT DATE, VALEUR FROM TABLE
    WHERE CLE1 = 12 AND CLE2 = 15 AND CLE3 = 17
    AND VALEUR < 600
    AND DATE >= DATEADD (DAY, -3, GETDATE())
    AND ((SELECT COUNT(*) FROM TABLE
    WHERE CLE1 = 12 AND CLE2 = 15 AND CLE3 = 17
    AND VALEUR >= 600
    AND DATE >= DATEADD (DAY, -3, GETDATE())) = 0)
    En gros : la req retourne les enregistrements avec valeur < 600 depuis 3 jours, seulement si sur la même période il n'existe aucun enregistrement avec valeur >= 600
    Ca marche, mais ce n'est pas très élégant, et c'est surtout incomplet :
    Si il n'existe aucun enregistrement depuis 3 jours, il faut que j'arrive à vérifier si la dernière valeur avant les 3 jours est < 600...



    Citation Envoyé par vanagreg Voir le message
    Bonjour,

    Tu peux certainement tout faire en une seule requête. Il faudrait que tu nous donnes un jeu de données avec le résultat attendu.

  7. #7
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    J'ai un peu de mal avec vos définitions.

    Du coup j'ai pondu une belle requête usine à gaz, mais qui donne le bon résultat...
    Il suffit juste de vérifier la première et la seconde colonne pour savoir si c'est plus petit ou plus grand que 600 dans les 3 et 4 derniers jours.

    Code sql : 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
    32
    33
    34
    35
    with calendar (date)
    as
    (
    	select cast(getdate() as date)
    	union all
    	select dateadd(day, -1, date) from calendar where date > dateadd(day, -4, cast(getdate() as date))
    ),
    last (cle1, cle2, cle3, der)
    as
    (
    	select h.cle1, h.cle2, h.cle3, max(h.date)
    	from historique h
    	group by h.cle1, h.cle2, h.cle3
    ),
    intervalle (cle1, cle2, cle3, deb, fin, valeur)
    as
    (
    	select h.cle1, h.cle2, h.cle3, h.date, min(isnull(n.date, dateadd(day, 1, cast(getdate() as date)))), h.valeur
    	from historique h
    	inner join last l on l.cle1 = h.cle1 and l.cle2 = h.cle2 and l.cle3 = h.cle3 and l.der <= h.date
    	left outer join historique n on n.cle1 = h.cle1 and n.cle2 = h.cle2 and n.cle3 = h.cle3 and n.date > h.date
    	where h.date > dateadd(day, -30, cast(getdate() as date))
    	group by h.cle1, h.cle2, h.cle3, h.date, h.valeur
    ),
    complet (cle1, cle2, cle3, date, valeur)
    as
    (
    	select i.cle1, i.cle2, i.cle3, c.date, i.valeur
    	from intervalle i
    	inner join calendar c on c.date >= i.deb and c.date < i.fin
    	where c.date >= dateadd(day, -4, cast(getdate() as date))
    )
    select c.cle1, c.cle2, c.cle3, max(case when c.date > dateadd(day, -3, cast(getdate() as date)) then c.valeur else 0 end), max(case when c.date > dateadd(day, -4, cast(getdate() as date)) then c.valeur else 0 end)
    from complet c
    group by c.cle1, c.cle2, c.cle3

    Y'a très probablement moyen de faire plus simple, j'avoue que là je me suis lâché
    On ne jouit bien que de ce qu’on partage.

  8. #8
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 766
    Points : 52 561
    Points
    52 561
    Billets dans le blog
    5
    Par défaut
    Quelque chose partant de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT SUM(CASE WHEN VALEUR < 600 THEN 1 ELSE 0 END) AS INF, 
           SUM(CASE WHEN VALEUR < 600 THEN 0 ELSE 1 END) AS SUP
    WHERE CLE1 = 12 AND CLE2 = 15 AND CLE3 = 17
    AND DATE >= DATEADD (DAY, -3, GETDATE())
    Pourrait vous aider.

    SVP respectez la charte de postage afin que l'on puisse vous aider :
    https://www.developpez.net/forums/d9...vement-poster/

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    Août 2004
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 282
    Points : 119
    Points
    119
    Par défaut
    Merci pour vos dernières réponses qui m'ont permis d'avancer sur mon problème
    Je marque en résolu et vous souhaite une bonne fin de semaine

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 08/10/2009, 12h18
  2. [MySQL] Optimisation code requète sql multi conditionnée
    Par mac7474 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 13/08/2009, 09h51
  3. Requête SQL multi schémas
    Par Monfy29 dans le forum SQL
    Réponses: 4
    Dernier message: 15/08/2008, 13h06
  4. [Debutant] Requête SQL Multi-Tables
    Par Superbretzel dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 16/02/2008, 11h47
  5. [SQL] Simplifier une requête SQL ?
    Par renaud26 dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 29/04/2006, 13h50

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