|
| Select imbriqué dans un autre Select en HFSQL |
| Iniciado por Yvan, 22,jul. 2020 16:42 - 16 respuestas |
| |
| | | |
|
| |
Miembro registrado 214 mensajes |
|
| Publicado el 22,julio 2020 - 16:42 |
Bonjour,
Question souvent posée, je sais... Mais qui sais, peut-être un petit refresh de temps en temps fera avancer le Schmilblik.
Ce que j'explique ici fonctionne très bien sur une DB SQL Server, donc ça fonctionne, c'est relativement basique et j'en ai également besoin pour un logiciel fonctionnant sur SQL Server et HFSQL.
SELECT MATERIEL.REFERENCE AS [REF] ,SUM(CASE WHEN MVTS.SENS IN ('SO','SOC') THEN MVTS.QTE*-1 WHEN MVTS.SENS IN ('EN','ENC') THEN MVTS.QTE END) AS [QTE] ,(SELECT TOP 1 M.PMP FROM MVTS AS M WHERE M.REFERENCE=MATERIEL.REFERENCE ORDER BY M.DateHeureModification DESC) AS [PrixMP] FROM MATERIEL LEFT JOIN MVTS ON MVTS.REFERENCE=MATERIEL.REFERENCE GROUP BY MATERIEL.REFERENCE
Ce qui coince ici est le ,(SELECT TOP 1 M.PMP FROM MVTS as M WHERE M.REFERENCE=MATERIEL.REFERENCE ORDER BY M.DateHeureModification DESC) as [PrixMP] dans ma clause SELECT initiale.
Le message d'erreur renvoyé par le CC HFSQL n'est pas cohérent (je pense) : Initialisation de la requête impossible. La sous-requête ne doit contenir qu'une seule colonne résultat. Erreur détectée : ,(>>>>SELECT TOP 1 M.PMP FROM MVTS as M WHERE M.REFERENCE=MATERIEL.REFERENCE ORDER BY M.DateHeureModification DESC<<<<) as [PrixMP] Car la sous-requête ne peut me renvoyer qu'un seul résultat
Et je n'ai pas trop d'idée sur une autre manière d'arriver à mes fins, si ce n'est de collecter cette info séparément et la combiner ensuite.
Merci! |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 2.682 mensajes |
|
| Publicado el 23,julio 2020 - 12:28 |
Bonjour,
Avec HFSQL tu n'as pas d'autre solution, le fait de mettre un order by dans la sous-requête perd complètement HFSQL et ce depuis des années. Peut-être y aura-t-il une correction un jour ???
-- Cordialement,
Philippe SAINT-BERTIN |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 214 mensajes |
|
| Publicado el 23,julio 2020 - 13:52 |
Merci Philippe,
Je ne vais pas rentrer dans le débat des pour et des contres HFSQL mais c'est pénible tout de même ... On va donc faire un brol parallèle dans lequel je peux oublier également les clauses du genre rank over partition qui permettent ce type de classement des données. A+ |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 2.682 mensajes |
|
| Publicado el 23,julio 2020 - 15:01 |
Ce que tu peux faire éventuellement c'est faire une requête à part qui ne fait que
SELECT TOP 1 M.PMP FROM MVTS AS M WHERE ORDER BY M.DateHeureModification DESC
Ensuite tu peux faire un join des 2 requêtes
-- Cordialement,
Philippe SAINT-BERTIN |
| |
| |
| | | |
|
| | |
| |
| Publicado el 23,julio 2020 - 15:46 |
As tu testé ta sous requete toute seule ?
Je demande parce que, j'ai essayé "SELECT TOP 1 M.PMP FROM MVTS as M WHERE M.REFERENCE=MATERIEL.REFERENCE ORDER BY M.DateHeureModification DESC" sur une de mes bases HFSQL, dans le centre de controle (en remplacant les noms de champs et de fichiers, bien entendu), et j'ai obtenu une erreur sql....
Il a fallu que je déplace le 'as M' AVANT le from pour que la syntaxe soit acceptée...
Ca expliquarait l'erreur qui dit "Initialisation de la requête impossible. La sous-requête ne doit contenir qu'une seule colonne résultat."
Etant en erreur, elle ne renvoit pas une colonne résultat...
Je ne sait pas si ca résoudrale problème global, mais bon... |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 214 mensajes |
|
| Publicado el 23,julio 2020 - 16:11 |
Argus, oui j'ai testé et oui ça fonctionne, d'ailleurs le tout fonctionne bien sous SQL-Server. J'avais même d'ailleurs remplacé le left join mvts par un join mvts car ce message d'erreur dans ce cas m'aurait paru plus "logique", mais ce n'est pas le soucis...
Philippe, non, ce n'est pas si simple ... que je t'explique : j'ai une table de mouvements, avec une rubrique PMP, un mouvement concerne un article (rubrique REFERENCE) a une date de dernière mise à jour (rubrique DateHeureModification) A chaque création modification d'une ligne de cette table, le PMP est calculé et stocké dans PMP Donc ce qu'il me faut, c'est la dernière ligne de mouvement par article, et pas la dernière ligne de mouvement tout court D'ou ma remarque sur les clauses rank over partition super pratique pour ce genre de besoins ... |
| |
| |
| | | |
|
| | |
| |
| Publicado el 23,julio 2020 - 16:23 |
le fait que ca fonctionne sous sql serveur ne veut RIEN dire pour une autre base...
SQL est loin d'être uniforme entre bases et c'est précisément l'interet d'utiliser l'éditeur de requete au lieu de coder directement en sql L'éditeur de requete va TRADUIRE dans le language sql de la base cible à la volée et permettre une compatibilité du code entre bases.
Donc, si tu n'as pas testé ta sous requete toute seule directement dans le centre de contre HFSQL sur une base HFSQL, je te conseille de le faire, parceque ta syntaxe est en erreur chez moi, sous wx24 |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 214 mensajes |
|
| Publicado el 23,julio 2020 - 19:44 |
Angus,
Je sais que deux moteur de BDD ont des comportements différents et des syntaxes propres à chacun, j'ai bien fait mes tests sur les deux moteurs.
Ceci dit, tu ne peux pas isoler le sous select pour le tester "tout seul" car il comporte une référence à une table qui fait partie du select primaire (materiel.reference), c'est l'intérêt de la manoeuvre, donc en aucun cas tu ne sauras tester cette requête isolément telle quelle.
Du coup, pour en avoir le coeur net j'ai testé cette sous requête en indiquant une référence en dur, et la requête fonctionne : SELECT TOP 1 M.PMP FROM MVTS as M WHERE M.REFERENCE='000001' ORDER BY M.DateHeureModification DESC (encore heureux car plus basique c'est difficile) Comme le précise Philippe, c'est bien le order by dans le sous select qui pose problème (mais sans celui-ci la requête n'a aucun sens).
PS : il y a tout de même une erreur dans ma requête (pour du HFSQL j'entend), c'est que le group by doit contenir l'alias [PrixMP] |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 42 mensajes |
|
| Publicado el 24,julio 2020 - 11:10 |
Bonjour, perso, dans ce genre de situation, je mets le SELECT au niveau de la jointure, ce qui donnerait (je n'ai pas testé, simplement je me suis inspiré de code que j'utilise):
SELECT MATERIEL.REFERENCE as [REF] ,Sum(CASE WHEN MVTS.SENS IN ('SO','SOC') THEN MVTS.QTE*-1 WHEN MVTS.SENS IN ('EN','ENC') THEN MVTS.QTE END) AS [QTE] ,M.PMP as [PrixMP] FROM MATERIEL Left JOIN MVTS ON MVTS.REFERENCE=MATERIEL.REFERENCE Left JOIN (SELECT TOP 1 T1.PMP AS [PMP] FROM MVTS T1 ORDER by T1.DateHeureModification DESC) M ON M.REFERENCE=MATERIEL.REFERENCE |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 953 mensajes |
|
| Publicado el 24,julio 2020 - 13:02 |
bonjour,
je crois malheuresement que çà ne fonctionnera pas, le soucis est au niveau des sous requetes et de l'utilisation du ORDER BY
=> https://doc.pcsoft.fr/fr-FR/?2034009&name=Sous_requete ( dans les limites )
Il faudrait voir si vous n'arrivez pas obtenir le même resultat de votre sous requetes sans la close order by... |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 214 mensajes |
|
| Publicado el 24,julio 2020 - 14:45 |
Pascal,
Belle idée mais non ça ne fonctionne pas : Erreur dans le code SQL de la requête <>. Initialisation de la requête impossible. Mot ORDER inattendu
Christophe,
En effet, il faut se résoudre aux limitations biens réelles et contraignantes de ce SGBD, et non, sans le order by ça n'a plus de sens dans mon cas.
Merci tout de même... |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 42 mensajes |
|
| Publicado el 24,julio 2020 - 17:12 |
Autre suggestion issu d'une requete que nous utilisons. Il y a une sousu-requete sur une sous-requete afin de récupérer la date la plus récente sur une jointure:
SELECT MATERIEL.REFERENCE as [REF] ,Sum(CASE WHEN MVTS.SENS IN ('SO','SOC') THEN MVTS.QTE*-1 WHEN MVTS.SENS IN ('EN','ENC') THEN MVTS.QTE END) AS [QTE] ,M.PMP as [PrixMP] FROM MATERIEL Left JOIN MVTS ON MVTS.REFERENCE=MATERIEL.REFERENCE Left JOIN (SELECT TOP 1 T1.PMP AS [PMP] FROM MVTS T1 INNER JOIN (SELECT Max(T2.DateHeureModification) FROM MVTS) T2 ON T2.REFERENCE=T1.REFERENCE) M ON M.REFERENCE=MATERIEL.REFERENCE GROUP by MATERIEL.REFERENCE |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 558 mensajes |
|
| Publicado el 25,julio 2020 - 12:04 |
Bonjour, Je propose que tu éxécutes la sous requete seule (avce ton order), tu récupère le nom de la table temporaire (nom source de données) et tu fais le select dans cette source de onnée, ça va marcher à 100 % |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 558 mensajes |
|
| Publicado el 25,julio 2020 - 12:23 |
MonInterrogation est une Requête SQL = [ SELECT * FROM CLIENT ] HExécuteRequête(MonInterrogation) AutreInterrogation est une chaîne = "SELECT * FROM %1" AutreInterrogation = ChaîneConstruit(AutreInterrogation, MonInterrogation..Nom) ReqAvecMonInterrogation est une Source dede Données HExécuteRequêteSQL(ReqAvecMonInterrogation, AutreInterrogation)
C'est le code d'illustration |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 214 mensajes |
|
| Publicado el 25,julio 2020 - 18:48 |
Merci Ralph, Le problème est que la sous requête seule n'a pas de sens car au vu de la structure de cette table, seule un requête avec un SGBD acceptant des clauses comme rank over partition de SQL-Server. Le truc c'est que ma table contient des mouvements d'articles, chaque ligne a une colonne PMP, la valeur courante du PMP d'un article se trouve dans la ligne la plus récente du mouvement de CET article. Je dois donc obtenir le select TOP 1 order by date de chaque article individuellement. L'imbrication des 2 requêtes permet ça, du moins sur du SQL-Server. Une requête unique séparée serait aussi possible sur du SQL-Server avec les clauses décrites plus haut, mais en HFSQL, ces clauses (très spécifiques je l'avoue) n'existent pas, et l'imbrication reste fort limitée.
Pascal, j'ai essayé ta requête mais ça ne fonctionne pas, je retiens tout de même l'idée et je vais essayer de creuser ...
Merci en tous les cas de vos efforts pour trouver une parade!  |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 558 mensajes |
|
| Publicado el 25,julio 2020 - 19:33 |
Tu decoupes en 3 requetes
MonInterrogation est une Requête SQL = [ ELECT TOP 1 T1.PMP AS [PMP] FROM MVTS T1 ] HExécuteRequête(MonInterrogation) AutreInterrogation est une chaîne = "SELECT * FROM %1" AutreInterrogation = ChaîneConstruit(AutreInterrogation, MonInterrogation..Nom) ensuile la ligne LEFT JOIN (SELECT TOP 1 T1.PMP AS [PMP] FROM MVTS T1 INNER JOIN (SELECT MAX(T2.DateHeureModification) FROM MVTS) T2 ON T2.REFERENCE=T1.REFERENCE) M ON M.REFERENCE=MATERIEL.REFERENCE
devient
[code:sql] Left JOIN (SELECT %1 INNER JOIN (SELECT Max(T2.DateHeureModification) FROM MVTS) T2 ON T2.REFERENCE=T1.REFERENCE) M ON M.REFERENCE=MATERIEL.REFERENCE [/code]
avec chaine construit, tu remplace %1 par MonInterrogation..Nom qui est une variable. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 558 mensajes |
|
| Publicado el 25,julio 2020 - 19:36 |
Tu crée la requete
MonInterrogation est une Requête SQL = [ SELECT TOP 1 T1.PMP AS [PMP] FROM MVTS T1 ] HExécuteRequête(MonInterrogation) AutreInterrogation est une chaîne = "SELECT * FROM %1" AutreInterrogation = ChaîneConstruit(AutreInterrogation, MonInterrogation..Nom) ensuile la ligne LEFT JOIN (SELECT TOP 1 T1.PMP AS [PMP] FROM MVTS T1 INNER JOIN (SELECT MAX(T2.DateHeureModification) FROM MVTS) T2 ON T2.REFERENCE=T1.REFERENCE) M ON M.REFERENCE=MATERIEL.REFERENCE
devient
LEFT JOIN (SELECT %1 INNER JOIN (SELECT MAX(T2.DateHeureModification) FROM MVTS) T2 ON T2.REFERENCE=T1.REFERENCE) M ON M.REFERENCE=MATERIEL.REFERENCE
avec chaine construit, tu remplace %1 par MonInterrogation..Nom qui est une variable. C'est tout |
| |
| |
| | | |
|
| | | | |
| | |
|