sql - valores - Cómo reutilizar una columna de resultados en una expresión para otra columna de resultados
sumar por grupos en sql (9)
Al igual que:
SELECT
turnover,
cost,
turnover - cost as profit
from (
(SELECT SUM(...) FROM ...) as turnover,
(SELECT SUM(...) FROM ...) as cost
) as partial_sums
Ejemplo:
SELECT
(SELECT SUM(...) FROM ...) as turnover,
(SELECT SUM(...) FROM ...) as cost,
turnover - cost as profit
Claro que esto no es válido (al menos en Postgres) pero, ¿cómo lograr lo mismo en una consulta sin volver a escribir la subconsulta dos veces?
Creo que lo siguiente funcionará:
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);
No probado en animales - ¡serás el primero! :-)
Comparte y Disfruta.
De hecho, trabajé mucho en esto y golpeé muchas paredes de ladrillo, pero finalmente descubrí una respuesta, más de un hack, pero funcionó muy bien y redujo la sobrecarga de lectura de mis consultas en un 90% ...
Así que, en lugar de duplicar la consulta correlacionada muchas veces para recuperar varias columnas de la subconsulta, solo usé concat todos los valores que quiero devolver en una varchar separada por comas, y luego los desenrollo nuevamente en la aplicación ...
Así que en lugar de
select a,b,
(select x from bigcorrelatedsubquery) as x,
(select y from bigcorrelatedsubquery) as y,
(select z from bigcorrelatedsubquery) as z
from outertable
Ahora hago
select a,b,
(select convert(varchar,x)+'',''+convert(varchar,x)+'',''+convert(varchar,x)+'',''
from bigcorrelatedsubquery) from bigcorrelatedquery) as xyz
from outertable
group by country
Ahora tengo los tres valores ''escalares'' correlacionados que necesitaba, pero solo tuve que ejecutar la subconsulta correlacionada una vez en lugar de tres veces.
Esto es bastante antiguo, pero me encontré con este problema y vi esta publicación, pero no pude resolver mi problema con las respuestas dadas, por lo que finalmente llegué a esta solución:
si su consulta es:
SELECT
(SELECT SUM(...) FROM ...) as turnover,
(SELECT SUM(...) FROM ...) as cost,
turnover - cost as profit
puede convertirlo en una subconsulta y luego usar los campos como:
SELECT *,(myFields.turnover-myFields.cost) as profit
FROM
(
SELECT
(SELECT SUM(...) FROM ...) as turnover,
(SELECT SUM(...) FROM ...) as cost
) as myFields
No estoy completamente seguro de si esta es una mala forma de hacer las cosas, pero en cuanto al rendimiento, me parece bien que consultar más de 224,000
registros tardó 1.5 segundos en no saber si luego se convirtió en 2x de la misma consulta secundaria por DB.
Podrías reutilizar la consulta así:
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
Esto es equivalente a:
SELECT *
FROM(
SELECT
TURNOVER.sum as SUM_TURNOVER
FROM
(
SELECT SUM(...) FROM ...)
)AS TURNOVER,
(
SELECT SUM(...) FROM ...
)AS COST
WHERE ....
) AS a
Hay un punto a tener en cuenta aquí. El primer método es más legible y reutilizable, pero el segundo método puede ser más rápido, porque la base de datos podría elegir un mejor plan para ello.
Puedes usar variables definidas por el usuario como esta
SELECT
@turnover := (SELECT SUM(...) FROM ...),
@cost := (SELECT SUM(...) FROM ...),
@turnover - @cost as profit
Tal vez la cláusula "con" sql podría ayudar, como se presenta aquí http://orafaq.com/node/1879 (otras bases de datos como Postgres también lo hacen, no solo oracle).
Utilice una aplicación de cruz o exterior.
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
SELECT turnover, cost, turnover - cost
FROM
(
SELECT
(SELECT ...) as turnover,
(SELECT ...) as cost
) as Temp