2010-11-18 10 views
37

Ejemplo:cómo reutilizar una una columna en una expresión de otro resultado columna

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

Seguro que esto no es válido (por lo menos en Postgres) pero la forma de lograr lo mismo en una consulta sin reescribir la sub-consulta ¿dos veces?

+0

Depende de los detalles, como columnas y tablas involucradas. –

+0

@OMG Ponis: ¿Me gusta? ¿No hay una manera general para tal? – Wernight

+0

Estoy de acuerdo con @OMG. Dicho esto, si puede escribir * una * subconsulta que devuelva tanto 'turnover' como' cost' como columnas, la consulta envuelta alrededor de esa subconsulta puede realizar 'turnover-cost'. Para obtener más detalles, necesitaremos algunos detalles sobre su esquema. –

Respuesta

40

así:

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

Normalmente cuando haces 'seleccionar de la tabla1, tabla2' obtienes la UNIÓN CRUZADA de las dos tablas. ¿Qué hace 'select from (table1, table2) como bla' (como lo has hecho aquí) con las dos tablas? –

+1

@CharlBotha: no se selecciona desde (foo, bar). Es [seleccionar] (seleccionar suma de foo), (seleccionar suma de barra) [de nada]. –

+0

En su ejemplo anterior, tiene '... de ((seleccione ...) como facturación, (seleccione ...) como costo) como partial_sums' - Todavía me pregunto cómo exactamente la facturación y el costo sub- Selects se combinan? –

4
SELECT turnover, cost, turnover - cost 
FROM 
(
SELECT 
(SELECT ...) as turnover, 
(SELECT ...) as cost 
) as Temp 
+0

Esos son alias de tabla, no alias de columna ... –

+0

si la facturación y el costo son alias de tabla, definitivamente no se puede hacer esto: facturación - costo como ganancia –

+0

Inválido: ERROR: la sub consulta en FROM debe tener un alias SUGERENCIA: Por ejemplo, FROM (SELECT ...) [AS] foo. – Wernight

3

creo que el siguiente trabajo:

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 probados en animales - podrás primero! :-)

Comparta y disfrute.

4

Realmente trabajé mucho en esto, y golpeé muchas paredes de ladrillo, pero finalmente descubrí una respuesta, más bien un truco, pero funcionó muy bien y reduje la carga 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, acabo de utilizar concat todos los valores que quiero devolver en una varma separada por comas, y luego desenrollérselos 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 

hago ahora

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 correlacionados '' escalares que necesitaba pero sólo tuvimos que ejecutar la consulta correlacionada vez en lugar de tres veces.

+0

Lo que debería haber hecho es 'JOIN' la' bigcorrelatedsubquery' con 'outertable' una vez, en lugar de repetirlo varias veces o recurrir al hack de concat. Incluso en el peor de los casos, podría haber considerado esa subconsulta como un CTE para evitar repetirla. –

5

Quizás el sql "con" cláusula podría ayudar, como se presenta aquí http://orafaq.com/node/1879 (otras bases de datos como PostgreSQL lo hacen así, no sólo Oracle).

+1

Esta función se denomina "expresiones de tabla común", también conocida como CTE. Consulte http://stackoverflow.com/questions/2686919/is-possible-to-reuse-subqueries – Vadzim

10

Usted puede volver a utilizar la consulta como la siguiente:

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 destacar aquí. El primer método es más legible y reutilizable, pero el segundo método podría ser más rápido, porque el DB podría elegir un mejor plan para él.

+0

esta es la mejor manera de hacer que el código sea legible con más de una subconsulta ... –

0

Usar una cruz aplica o se aplica 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 
0

esto es bastante viejo, pero me encontré con este problema y vio a este post, pero aún no ha logran solucionar mi problema con las respuestas dadas por lo que con el tiempo 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 sub consulta y luego usar los campos tales como:

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

) as myFields 

no estoy del todo seguro de si esta es una mala forma de hacer las cosas, pero en cuanto al rendimiento me parece bien consultar 224,000 los registros tardaron 1,5 segundos no estoy seguro de si más tarde se convirtió en 2x de la misma sub consulta de DB.

Cuestiones relacionadas