PostgreSQL: utiliser une colonne calculée dans la même requête
j'ai de la difficulté à utiliser une colonne calculée dans postgres. Un code similaire qui fonctionne en SQL est donné ci-dessous, est-il possible de le recréer en PostgreSQL
?
select cost_1, quantity_1, cost_2, quantity_2,
(cost_1 * quantity_1) as total_1,
(cost_2 * quantity_2) as total_2,
(calculated total_1 + calculated total_2) as total_3
from data;
PostgreSQL
un code similaire renvoie l'erreur:
les colonnes total_1 et total_2 n'existent pas.
5 réponses
vous devez envelopper la déclaration SELECT dans une table dérivée afin de pouvoir accéder à la colonne alias:
select cost1,
quantity_1,
cost_2,
quantity_2
total_1 + total_2 as total_3
from (
select cost_1,
quantity_1,
cost_2,
quantity_2,
(cost_1 * quantity_1) as total_1,
(cost_2 * quantity_2) as total_2
from data
) t
Il n'y aura pas de perte de performances.
(je suis vraiment surpris de voir que l'original de votre instruction SQL s'exécute dans un SGBD)
si vous n'aimez pas wraping requête entière avec outerquery, vous pouvez utiliser LATERAL
pour calculer intermédiaire total_1
et total_2
:
SELECT cost_1, quantity_1, cost_2, quantity_2, total_1, total_2,
total_1 + total_2 AS total_3
FROM data
,LATERAL(SELECT cost_1 * quantity_1, cost_2 * quantity_2) AS s1(total_1,total_2);
Sortie:
╔═════════╦═════════════╦═════════╦═════════════╦══════════╦══════════╦═════════╗
║ cost_1 ║ quantity_1 ║ cost_2 ║ quantity_2 ║ total_1 ║ total_2 ║ total_3 ║
╠═════════╬═════════════╬═════════╬═════════════╬══════════╬══════════╬═════════╣
║ 1 ║ 2 ║ 3 ║ 4 ║ 2 ║ 12 ║ 14 ║
║ 3 ║ 5 ║ 7 ║ 9 ║ 15 ║ 63 ║ 78 ║
║ 10 ║ 5 ║ 20 ║ 2 ║ 50 ║ 40 ║ 90 ║
╚═════════╩═════════════╩═════════╩═════════════╩══════════╩══════════╩═════════╝
en règle générale, il y a deux choses que vous devez savoir sur le SELECT
l'article:
- bien qu'il soit écrit premier, il est évalué dernière, à l'exception de l'
ORDER BY
l'article. C'est pourquoi vous ne pouvez pas utiliser de champs calculés ou d'alias dans une autre clause (en particulierWHERE
l'article) sauf dans leORDER BY
l'article. - Calculs dans le
SELECT
la clause est exécutée en parallèle, ou du moins sont manipulés comme s'ils l'étaient. C'est pourquoi vous ne pouvez pas utiliser un calcul comme faisant partie d'un autre.
Donc, la réponse courte est que vous ne pouvez pas, et c'est par la conception.
L'exception notable à cela est Microsoft Access, où vous pouvez en effet utiliser des calculs dans les colonnes suivantes et WHERE
les clauses. Cependant, bien que cela soit pratique, ce n'est pas vraiment un avantage: ne pas suivre les principes ci-dessus est moins efficace. Mais C'est OK pour les bases de données de service léger, ce qui est ce à quoi L'accès est censé être utilisé.
si vous voulez vraiment réutiliser les résultats calculés, vous aurez besoin d'une requête séparée, soit sous la forme d'une sous-requête ou comme une Expression commune de Table. Les CTE sont beaucoup plus faciles à utiliser, car ils sont plus clairs à lire.
Modifier
sans changer le point de la réponse originale, j'ai pensé que je pourrais ajouter que je pense que cette explication est peut-être un peu mesquin.
Moderne Sgbd mis beaucoup d'efforts dans la planification et l'optimisation de requêtes, de sorte qu'il n'est plus correct, si jamais, que la requête est réellement exécutées dans un ordre particulier. Pour autant que je puisse voir, il n'y a pas de technique raison pour laquelle l'optimiseur ne pouvait pas regarder à l'avance et incorporer des résultats calculés dans l'analyse de la requête, même si c'est seulement pour substituer des expressions.
eh bien ...
select cost_1, quantity_1, cost_2, quantity_2,
cost_1 * quantity_1 as total_1,
cost_2 * quantity_2 as total_2,
(cost_1 * quantity_1 + cost_2 * quantity_2) as total_3
from data;
Vous essayez d'utiliser un alias de colonne dans une expression. Si un système vous permet de faire ça, c'est juste du sucre syntaxique. Cela devrait fonctionner dans n'importe quel dialecte SQL.
select
cost_1
,quantity_1
,cost_2
,quantity_2
,cost_1 * quantity_1 as total_1
,cost_2 * quantity_2 as total_2
,(cost_1 * quantity_1) + (cost_2 * quantity_2) as total_3
from data;