Comment réutiliser une colonne de résultat dans une expression pour une autre colonne de résultat

Exemple:

SELECT (SELECT SUM(...) FROM ...) as turnover, (SELECT SUM(...) FROM ...) as cost, turnover - cost as profit 

Bien sûr, cela est invalide (au moins dans Postgres), mais comment obtenir la même chose dans une requête sans réécrire la sous-requête deux fois?

Ainsi:

 SELECT turnover, cost, turnover - cost as profit from ( (SELECT SUM(...) FROM ...) as turnover, (SELECT SUM(...) FROM ...) as cost ) as partial_sums 

Vous pouvez réutiliser la requête comme ceci:

 WITH TURNOVER AS ( SELECT SUM(...) FROM ...) ), COST AS( SELECT SUM(...) FROM ... ) SELECT * FROM( SELECT TURNOVER.sum as SUM_TURNOVER FROM TURNOVER,COST WHERE .... ) AS a 

Ceci est équivalent à:

 SELECT * FROM( SELECT TURNOVER.sum as SUM_TURNOVER FROM ( SELECT SUM(...) FROM ...) )AS TURNOVER, ( SELECT SUM(...) FROM ... )AS COST WHERE .... ) AS a 

Il y a un point à noter ici. La première méthode est plus lisible et réutilisable, mais la seconde méthode peut être plus rapide, car la firebase database peut choisir un meilleur plan.

Peut-être que la clause sql “with” pourrait aider, comme présenté ici http://orafaq.com/node/1879 (d’autres bases de données telles que Postgres le font également, pas seulement Oracle).

 SELECT turnover, cost, turnover - cost FROM ( SELECT (SELECT ...) as turnover, (SELECT ...) as cost ) as Temp 

En fait, j’ai fait beaucoup de travail là-dessus et j’ai heurté de nombreux murs de briques, mais j’ai finalement trouvé une réponse – plus un hack – mais cela a très bien fonctionné et a réduit de 90% le temps de lecture de mes requêtes ….

Donc, plutôt que de dupliquer la requête corrélée plusieurs fois pour récupérer plusieurs colonnes de la sous-requête, je viens d’utiliser concaténer toutes les valeurs que je veux renvoyer dans un varchar séparé par des virgules, puis de les dérouler à nouveau dans l’application …

Donc au lieu de

 select a,b, (select x from bigcorrelatedsubquery) as x, (select y from bigcorrelatedsubquery) as y, (select z from bigcorrelatedsubquery) as z from outertable 

Je fais maintenant

 select a,b, (select convert(varchar,x)+','+convert(varchar,x)+','+convert(varchar,x)+',' from bigcorrelatedsubquery) from bigcorrelatedquery) as xyz from outertable group by country 

J’ai maintenant les trois valeurs «scalaires» corrélées dont j’avais besoin, mais je devais seulement exécuter la sous-requête corrélée une fois au lieu de trois.

Je pense que ce qui suit fonctionnera:

 SELECT turnover, cost, turnover-cost as profit FROM (SELECT 1 AS FAKE_KEY, SUM(a_field) AS TURNOVER FROM some_table) a INNER JOIN (SELECT 1 AS FAKE_KEY, SUM(a_nother_field) AS COST FROM some_other_table) b USING (FAKE_KEY); 

Pas testé sur les animaux – vous serez le premier! 🙂

Partager et profiter.

Vous pouvez utiliser des variables définies par l’utilisateur comme ceci

 SELECT @turnover := (SELECT SUM(...) FROM ...), @cost := (SELECT SUM(...) FROM ...), @turnover - @cost as profit 

http://dev.mysql.com/doc/refman/5.7/en/user-variables.html

Utilisez une croix appliquer ou appliquer à l’extérieur.

 SELECT Calc1.turnover, Calc2.cost, Calc3.profit from cross apply ((SELECT SUM(...) as turnover FROM ...)) as Calc1 cross apply ((SELECT SUM(...) as cost FROM ...)) as Calc2 /* Note there is no from Clause in Calc 3 below. This is how you can "stack" formulas like in excel. You can return any number of columns, not just one. */ cross apply (select Calc1.turnover - Calc2.cost as profit) as Calc3 

C’est assez vieux mais j’ai rencontré ce problème et j’ai vu ce post mais je n’ai pas réussi à résoudre mon problème en utilisant les réponses données donc je suis finalement arrivé à cette solution:

si votre requête est:

 SELECT (SELECT SUM(...) FROM ...) as turnover, (SELECT SUM(...) FROM ...) as cost, turnover - cost as profit 

vous pouvez le transformer en une sous-requête, puis utiliser les champs tels que:

 SELECT *,(myFields.turnover-myFields.cost) as profit FROM ( SELECT (SELECT SUM(...) FROM ...) as turnover, (SELECT SUM(...) FROM ...) as cost ) as myFields 

Je ne suis pas tout à fait sûr que ce soit une mauvaise façon de faire, mais en ce qui concerne les 224,000 enregistrements, il me semble que 1,5 s ne serait pas sûr de le transformer en 2x de la même requête par DB.