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 :

Pourquoi pas de variable dans SELECT ?


Sujet :

Langage SQL

  1. #1
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut Pourquoi pas de variable dans SELECT ?
    Salut
    Juste une question...
    Pourquoi le SELECT ne peut pas prendre de variable?
    Une idée de la forme...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT colx, coly, varx, vary,...
    VAR varx=expression, vary=expression2
    FROM...
    WHERE <prédicat sur colonnes>
    HAVING <prédicat sur variable>
    dans laquelle VAR serait une clause optionnelle de l'instruction SELECT.
    Le code que je donne est assez simpliste, mais pensez aux requêtes complexes dans lesquelles on a souvent des répétitions d'expression qu'on voudrais factoriser.
    Au passage, MySQL accepte un alias dans le having du genre...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT left(prenom,2) AS initial FROM personne HAVING initial='AL'
    Alors pourquoi pas?
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 786
    Points
    30 786
    Par défaut
    A ma connaissance, cette notation n'est pas prévue dans le standard SQL.
    J'ai rencontré ce concept dans Teradata (<expresssion> (named <alias>)) qui précise bien que c'est une spécificité.
    Après s'il s'agit juste de factoriser, tu as aussi beaucoup de capacités avec les tables dérivées et les expressions de table.
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Merci de la contribution.
    Personnellement, je remplacerai ...
    Citation Envoyé par al1_24 Voir le message
    A ma connaissance, cette notation n'est pas prévue dans le standard SQL.
    par...
    Ce concept n'est pas encore dans le standard SQL.
    Qui sait, peut-être que la pertinence se présentera un jour.
    Citation Envoyé par al1_24 Voir le message
    J'ai rencontré ce concept dans Teradata (<expresssion> (named <alias>)) qui précise bien que c'est une spécificité.
    Ce sont les spécificités qui enrichissent le standard.
    Citation Envoyé par al1_24 Voir le message
    Après s'il s'agit juste de factoriser, tu as aussi beaucoup de capacités avec les tables dérivées et les expressions de table.
    Les tables dérivées (ou sous-requêtes) et les expressions de tables induisent forcement plus d'une boucle de lecture. Alors que le concept de variable est utilisé à chaque ligne.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  4. #4
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 786
    Points
    30 786
    Par défaut
    Avec un bon optimiseur, il n'est pas obligatoire que l'usage d''une table dérivée ou une expression de table se traduise en boucle.
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  5. #5
    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
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Par ailleurs, HAVING engendre un GROUP BY, (ce qui peut être couteux, donc pas forcément idéal non plus pour les performances lorsqu'il n'est pas nécessaire) mais surtout change la sémantique de la requete.

    D'ailleurs, votre requête ne sera pas valide si l'une des variables fait référence a l'une des colonnes de la table sans fonction d'agregation, justement en raison de l'absence de clause GROUP BY explicite.

    Enfin, pour ce qui est de MySQL qui accepte cette syntaxe, quand on voit comment il gère la dite clause GROUP BY, je ne pense pas que ce soit une référence à prendre en compte pour ce débat...

  6. #6
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Citation Envoyé par al1_24 Voir le message
    Avec un bon optimiseur, il n'est pas obligatoire que l'usage d''une table dérivée ou une expression de table se traduise en boucle.
    Veux-tu dire qu'une requête de la forme...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ...
    FROM (SELECT ... FROM <liste_from_interne>) AS r
    WHERE <prédicat>
    peut être transformé par un optimiseur sous la forme...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT ... FROM <liste_from_interne> WHERE <prédicat>
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    Par ailleurs, HAVING engendre un GROUP BY, (ce qui peut être couteux, donc pas forcément idéal non plus pour les performances lorsqu'il n'est pas nécessaire) mais surtout change la sémantique de la requete.

    D'ailleurs, votre requête ne sera pas valide si l'une des variables fait référence a l'une des colonnes de la table sans fonction d'agregation, justement en raison de l'absence de clause GROUP BY explicite.

    Enfin, pour ce qui est de MySQL qui accepte cette syntaxe, quand on voit comment il gère la dite clause GROUP BY, je ne pense pas que ce soit une référence à prendre en compte pour ce débat...
    admettons cela dans la définition actuelle des choses.
    D'où le fait que j'ai separé le WHERE et le HAVING.
    L'idée est de ...
    1. laisser intact le fonctionnement de WHERE i.e au niveau du moteur de stockage (accès aux blocs binaires de table et d'index)
    2. exécuter le HAVING au niveau du moteur de requête (l'espace mémoire de la requête) sans qu'il ne soit forcement lié à un GROUP BY

    Merci de vos contributions
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 763
    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 763
    Points : 52 554
    Points
    52 554
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par alassanediakite Voir le message
    Salut
    Juste une question...
    Pourquoi le SELECT ne peut pas prendre de variable?:
    Parce que c'est en pure opposition à la logique ensembliste. Il ne faudrait pas une variables scalaire, mais tout simplement un ensemble de données, donc une table; C'est pourquoi le SQL a statuer en proposant les tables temporaires.
    Pour info Chris Date a bien indiqué qu'il y avait aussi confusion entre le contenant et le contenu. Car en algèbre relationnelle le même terme désigne les deux.
    Dans les langages itératifs, il y a la notion de variable qui est le conteneur et la notion de valeur qui est le contenu.
    Chris Date à alors proposer qu'il y ait deux termes : la relation (le contenu) et la "relvar" (variable relationnelle, donc le conteneur).

    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/ * * * * *

  8. #8
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    SQLpro, la santé ça va?
    Que "SQL travaille sur des ensembles", je suis d'accord.
    Que "SQL soit un langage déclaratif", je suis d'accord.
    Mais que "SQL soit opposé à la réutilisation d'expression déjà calculée" je trouve que c'est mettre un frein au SGBDR.
    Merci pour la contribution et 1000% de santé pour toi.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  9. #9
    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
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par alassanediakite Voir le message
    exécuter le HAVING au niveau du moteur de requête (l'espace mémoire de la requête) sans qu'il ne soit forcement lié à un GROUP BY
    Justement, le HAVING est forcément lié à un GROUP BY, qu'il soit explicite, ou implicite.

  10. #10
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 379
    Points
    20 379
    Par défaut
    Citation Envoyé par alassanediakite Voir le message
    Salut
    Juste une question...
    Pourquoi le SELECT ne peut pas prendre de variable?
    parce que c'est tout simplement l'intérêt d'utiliser des langages de procédures stockées comme le PL-SQL (Oracle) ou le Transact SQL (MS SQL-SERVER).
    Faire des procédures stockées ça permet d'accéler des traitements sur des bases de données de manière puissance n...

  11. #11
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Citation Envoyé par aieeeuuuuu Voir le message
    Justement, le HAVING est forcément lié à un GROUP BY, qu'il soit explicite, ou implicite.
    J'ai pas dit le contraire. Je propose une évolution du SELECT (qui je pense l'améliore en temps): permettre au SELECT de réutiliser une expression déjà calculée. Une amélioration qui modifiera le comportement de HAVING.
    Citation Envoyé par Mat.M Voir le message
    parce que c'est tout simplement l'intérêt d'utiliser des langages de procédures stockées comme le PL-SQL (Oracle) ou le Transact SQL (MS SQL-SERVER).
    Faire des procédures stockées ça permet d'accéler des traitements sur des bases de données de manière puissance n...
    Je ne parle ni de boucle, ni de curseur, ni de gestion d'erreur, ni ...
    Juste permettre au SELECT de réutiliser une expression déjà calculée puisque c'est cela dont il s'agit!!!.
    Si vous voulez on peut poser la question autrement: Pourquoi ne pas permettre au SELECT de réutiliser une expression déjà calculée.
    Merci pour vos contributions.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  12. #12
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 379
    Points
    20 379
    Par défaut
    Citation Envoyé par alassanediakite Voir le message
    Pourquoi ne pas permettre au SELECT de réutiliser une expression déjà calculée
    un SELECT ne permet que de retourner les données de colonnes et non de calculer des expressions.
    Sauf de calculer des expressions mathématiques et retourner le résultat par exemple on peut faire SELECT 1+1 FROM table..
    Ou bien alors je n'ai pas du tout compris ta question il faudrait être plus explicite...

    Citation Envoyé par alassanediakite Voir le message
    Pourquoi le SELECT ne peut pas prendre de variable?
    Une idée de la forme...
    pour que le moteur d'interprétation des commandes SQL soit en mesure de faire cela il faudrait qu'il crée une pile de variables dynamique.
    Exactement comme lorsqu'on appelle une fonction dans un langage informatique procédural on passe des paramètres à la fonction
    Maintenant pourquoi les moteurs d'interprétation SQL ne peuvent pas faire ça je ne sais pas sans doute pour raison de rétro-compatibilité ;
    encore une fois il faut utiliser les langages de procédures stockées
    Citation Envoyé par alassanediakite Voir le message
    dans laquelle VAR serait une clause optionnelle de l'instruction SELECT.
    clause optionnelle ? Il faudrait être plus précis

  13. #13
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Citation Envoyé par Mat.M Voir le message
    ...encore une fois il faut utiliser les langages de procédures stockées
    Ce n'est pas un problème auquel je suis confronté et que cherche à résoudre.
    C'est un thème que je propose à débattre: faisabilité et pertinence
    Citation Envoyé par Mat.M Voir le message
    ...Maintenant pourquoi les moteurs d'interprétation SQL ne peuvent pas faire ça je ne sais pas sans doute pour raison de rétro-compatibilité ;
    Là tu es dans le débat et il faut (stp) clarifier ton propos.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  14. #14
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 379
    Points
    20 379
    Par défaut
    Citation Envoyé par alassanediakite Voir le message
    Là tu es dans le débat et il faut (stp) clarifier ton propos.
    @+
    ?? ce n'est pas faire un débat je ne peux pas faire de débat parce que j'ai précisément écris que je ne savais pas et al1_24 a parlé de compatibilité ; et si tu veux que l'on réponde avec pertinence à tes questions je t'ai posé des questions précisément
    Auxquelles tu n'as pas répondu

  15. #15
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut solution magique avec JOIN LATERAL
    Salut
    A force de chercher à vous convaincre de la pertinence, j'ai découvert une solution magique avec la jointure latérale (JOIN LATERAL).
    L'exemple est fait sur la résolution d'équation du second degré.
    Solution avec PostgreSQL
    La table contenant les coefficients...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    create table seconddegre(id serial primary key, a int, b int, c int);
    Insertion de trois lignes...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into seconddegre(a, b, c) values(1,1,-1),(1,0,-1),(1,-1,-2),(1,1,1);
    La requête standard...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    select b*b-4*a*c as delta, 
    	(case 
    	when b*b-4*a*c>=0 then
    	(-b-sqrt(b*b-4*a*c))/2*a
    	else null
    	end)  as x1, 
    	(case 
    	when b*b-4*a*c>=0 then
    	(-b+sqrt(b*b-4*a*c))/2*a
    	else null
    	end)  as x2
    from seconddegre
    Le résultat...
    delta x1 x2
    5 -1.61803398874989 0.618033988749895
    4 -1 1
    9 -1 2
    -3

    La requête avec JOIN LATERAL...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    select delta, 
    	(case 
    	when delta>=0 then
    	(-b-rdelta)/2*a
    	else null
    	end)  as x1, 
    	(case 
    	when delta>=0 then
    	(-b+rdelta)/2*a
    	else null
    	end)  as x2
    from seconddegre as sd
    join lateral (select sd.b*sd.b-4*sd.a*sd.c as delta, sqrt(abs(sd.b*sd.b-4*sd.a*sd.c)) as rdelta) as d on true
    Le résultat...
    delta x1 x2
    5 -1.61803398874989 0.618033988749895
    4 -1 1
    9 -1 2
    -3
    Bonus..., on peut même filtrer avec WHERE...
    Les équations qui on une solution...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    select delta, 
    	(case 
    	when delta>=0 then
    	(-b-rdelta)/2*a
    	else null
    	end)  as x1, 
    	(case 
    	when delta>=0 then
    	(-b+rdelta)/2*a
    	else null
    	end)  as x2
    from seconddegre as sd
    join lateral (select sd.b*sd.b-4*sd.a*sd.c as delta, sqrt(abs(sd.b*sd.b-4*sd.a*sd.c)) as rdelta) as d on true
    where delta>=0
    Il reste à chercher pour les agrégations.
    @+ et grand merci de vos contributions
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  16. #16
    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
    Points : 13 092
    Points
    13 092
    Par défaut
    il n'y a pas plus de variable dans cette requete.

    Si le débat porte uniquement sur la possibilité de réutiliser dans le WHERE des calculs (complexes a écrire, sinon aucune intérêt) définis dans le SELECT alors c'est différent.

    Et dans ce cas, on peut simplement utiliser des sous requêtes ou CTE, ce qui résout par la même occasion le problème des agrégats, ainsi que d'autres non évoqués comme l'utilisation de fonctions fenêtrées, qui ne sont pas non plus admises dans la clause WHERE.

  17. #17
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    aieeeuuuuu, chapeau
    Avec PostgreSQL, j'ai comparé les plans d’exécutions des différentes formes. Il en résulte que le JOIN LATERAL et la sous-requête donne des plans identiques (même avec jointure!).
    JOIN LATERAL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    select delta, 
    	(case 
    	when delta>=0 then
    	(-b-rdelta)/2*a
    	else null
    	end)  as x1, 
    	(case 
    	when delta>=0 then
    	(-b+rdelta)/2*a
    	else null
    	end)  as x2
    from seconddegre as sd 
    join lateral (select sd.b*sd.b-4*sd.a*sd.c as delta, sqrt(abs(sd.b*sd.b-4*sd.a*sd.c)) as rdelta) as d on true
    Nom : v1.png
Affichages : 487
Taille : 1,8 Ko
    SOUS REQUÊTE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    select delta, 
    	(case 
    	when delta>=0 then
    	(-b-rdelta)/2*a
    	else null
    	end)  as x1, 
    	(case 
    	when delta>=0 then
    	(-b+rdelta)/2*a
    	else null
    	end)  as x2
    from (select a, b, c, b*b-4*a*c as delta, sqrt(abs(b*b-4*a*c)) as rdelta from seconddegre) as r
    Nom : v1.png
Affichages : 487
Taille : 1,8 Ko
    CTE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    with r as(select a, b, c, b*b-4*a*c as delta, sqrt(abs(b*b-4*a*c)) as rdelta from seconddegre)
    select delta, 
    	(case 
    	when delta>=0 then
    	(-b-rdelta)/2*a
    	else null
    	end)  as x1, 
    	(case 
    	when delta>=0 then
    	(-b+rdelta)/2*a
    	else null
    	end)  as x2
    from r
    Nom : v2.png
Affichages : 358
Taille : 3,8 Ko
    En fait, j'ai toujours pensé que la sous-requête est entièrement exécutée (comme cte dans ce cas) avant la requête principale.
    @+ et encore merci pour vos contribution
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  18. #18
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 763
    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 763
    Points : 52 554
    Points
    52 554
    Billets dans le blog
    5
    Par défaut
    Plusieurs choses à dire sur votre exemple :

    1) SERIAL n'existe pas c'est spécifique à PostGreSQL. les mécanismes normalisés de génération des auto-incréments sont IDENTITY (interne à la table, donc proche du SERIAL) et SEQUENCE.

    2) l'opérateur d'intra-jointure LATERAL a été introduit par la norme SQL:1999 mais a été violemment critiqué car donnant des résultats potentiellement faux. Et d'ailleurs votre exemple donne un résultat faux car la ligne contenant des NULLs n'a pas de sens dans ce cas. De ce fait Microsoft à proposé de remplacer cet opérateur par l'opérateur APPLY décliné en deux versions : CROSS (produit cartésien) et OUTER (qui rajoute une ligne en cas de NULL dans les paramètres d'application). Oracle à d'ailleurs repris l'opérateur APPLY et quasiment abandonné l'opérateur LATERAL. APPLY a été proposé au comité de normalisation en remplacement de LATERAL, mais le mal est fait

    Si vous voulez utiliser un SGBDR qui respecte mieux la norme SQL (PostGreSQL s'en éloigne de plus en plus alors qu'ils y avaient été très proche) prenez SQL Server (vous avez même une version linux).
    https://www.microsoft.com/en-us/sql-...2017#resources

    En l'occurrence, voici ce qui se passe avec MS SQL Server :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    create table seconddegre(id int identity primary key, a int, b int, c int);
    insert into seconddegre(a, b, c) values(1,1,-1),(1,0,-1),(1,-1,-2),(1,1,1);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select delta, 
    	case When delta>=0 then (-b-rdelta)/2*a else null end  as x1, 
    	case when delta>=0 then (-b+rdelta)/2*a else null end  as x2
    from seconddegre as sd
    CROSS APPLY (select sd.b*sd.b-4*sd.a*sd.c as delta, sqrt(abs(sd.b*sd.b-4*sd.a*sd.c)) as rdelta) as d 
    where delta>=0;
    Et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    delta       x1                     x2
    ----------- ---------------------- ----------------------
    5           -1,61803398874989      0,618033988749895
    4           -1                     1
    9           -1                     2
    ne montre pas la ligne avec les NULLs qui n'a aucun sens !

    Alors que la solution en CTE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    with r as(select a, b, c, b*b-4*a*c as delta, sqrt(abs(b*b-4*a*c)) as rdelta from seconddegre)
    select delta, 
    	case When delta>=0 then (-b-rdelta)/2*a else null end  as x1, 
    	case when delta>=0 then (-b+rdelta)/2*a else null end  as x2
    from r;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    delta       x1                     x2
    ----------- ---------------------- ----------------------
    5           -1,61803398874989      0,618033988749895
    4           -1                     1
    9           -1                     2
    -3          NULL                   NULL
    Sur les plans de requête... Il n'y a évidemment pas assez de données pour obtenir une différence sensible dans les plans. En effet en cas de faible cardinalité, l'opérateur de jointure à privilégier sera la boucle imbriquée. Néanmoins, SQL Server montre que la CTE est légèrement plus couteuses et c'est normal car légèrement plus complexe.

    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/ * * * * *

  19. #19
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Citation Envoyé par SQLpro Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select delta, 
    	case When delta>=0 then (-b-rdelta)/2*a else null end  as x1, 
    	case when delta>=0 then (-b+rdelta)/2*a else null end  as x2
    from seconddegre as sd
    CROSS APPLY (select sd.b*sd.b-4*sd.a*sd.c as delta, sqrt(abs(sd.b*sd.b-4*sd.a*sd.c)) as rdelta) as d 
    where delta>=0;
    Enlevez le WHERE vous obtiendrez les NULL!!!
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  20. #20
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Je ne comprend pas vraiment le + et le - des postes précédents.
    Citation Envoyé par SQLpro Voir le message
    l'opérateur d'intra-jointure LATERAL a été introduit par la norme SQL:1999 mais a été violemment critiqué car donnant des résultats potentiellement faux. Et d'ailleurs votre exemple donne un résultat faux car la ligne contenant des NULLs n'a pas de sens dans ce cas. De ce fait Microsoft à proposé de remplacer cet opérateur par l'opérateur APPLY décliné en deux versions : CROSS (produit cartésien) et OUTER (qui rajoute une ligne en cas de NULL dans les paramètres d'application). Oracle à d'ailleurs repris l'opérateur APPLY et quasiment abandonné l'opérateur LATERAL. APPLY a été proposé au comité de normalisation en remplacement de LATERAL, mais le mal est fait
    pourquoi cette position inexplicable sur SQL SERVER: quand il respecte la norme on le félicite, sinon c'est la norme qui est critiquée?
    J'ai montré (en parlant du where) que (dans la situation actuelle) apply et lateral donnent le même résultat. Ce qui m'a valu (-1)!!!
    D'ailleurs pourquoi la ligne du null serait un non sens?
    Je rappelle que nous somme sur un forum scientifique et non politique ou religieux!!!
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. variables pas toutes liées dans select imbriqué
    Par mialy.rakot dans le forum SQL
    Réponses: 10
    Dernier message: 17/02/2011, 06h59
  2. [MySQL] Variable dans SELECT
    Par malabarbe dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 30/01/2010, 16h39
  3. [MySQL] Erreur variable dans select
    Par asmrct dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 16/06/2008, 16h16
  4. [SERVER] Pourquoi pas de make dans mac os x server 10.4.9
    Par Khaled.Noordin dans le forum Développement OS X
    Réponses: 2
    Dernier message: 29/05/2007, 16h55
  5. Réponses: 4
    Dernier message: 30/05/2006, 17h21

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