SQL - consulta SELECT, Hacer operaciones con el resultado de otra columna

 
Vista:
sin imagen de perfil
Val: 37
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

consulta SELECT, Hacer operaciones con el resultado de otra columna

Publicado por Jorge (19 intervenciones) el 18/04/2017 17:09:46
Hola, buenos días, tengo una duda.

Supongamos que tuviese la siguiente consulta,
donde "a" y "monto" serían campos de la tabla "TB"
y OP1 es el nombre de la columna con los resultados de la operación
1
2
3
4
5
6
7
8
SELECT
monto,
  CASE WHEN a=1 THEN (monto * 10)+(monto/51)
  CASE WHEN a=2 THEN (monto + 28)+(monto*87)
  CASE WHEN a=3 THEN (monto / 15)+(monto*1.158)
  ELSE 0
END AS OP1
FROM TB

ahora la pregunta,
¿Cómo podría hacer otra columna con operaciones que dependan de los resultados de la columna OP1?
digamos así:
1
2
3
4
5
6
7
8
9
10
11
12
SELECT
monto,
  CASE WHEN a=1 THEN (monto * 10)+(monto/51)
  CASE WHEN a=2 THEN (monto + 28)+(monto*87)
  CASE WHEN a=3 THEN (monto / 15)+(monto*1.158)
  ELSE 0
END AS OP1,
  CASE WHEN OP1>0 THEN OP1*(-1)
  CASE WHEN OP1<0 THEN OP1/5
  ELSE 0
END AS OP2
FROM TB
¿Se puede hacer algo así? (no se, con variables tal vez, pero no se como)
le pongo DECLARE @miOP1 numeric(15,7) al comienzo pero
no se como asignarle el valor el valor de OP1
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 806
Bronce
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

consulta SELECT, Hacer operaciones con el resultado de otra columna

Publicado por leonardo_josue (1173 intervenciones) el 18/04/2017 18:26:39
Hola Jorge:

No nos dices con qué BD estás trabajando, pero en realidad creo que el problema aplica para todos.

La cuestión aquí es que la columna OP1 es una columna calculada y por lo tanto "existe" sólo después de la ejecución de la consulta, seguramente al tratar de hacer lo que pretendes obtienes un error que te dice que el campo OP1 no existe o algo así. Para resolverlo, lo puedes hacer de dos formas, una utilizando subconsultas y otra haciendo los cálculos en ambos CASE-WHEN, veamos un ejemplo de cómo sería en MySQL...

Supongamos que tenemos esta tabla;

1
2
3
4
5
6
7
8
9
10
11
12
mysql> SELECT * FROM tabla;
+------+-------+
| a    | monto |
+------+-------+
|    1 |     1 |
|    2 |     1 |
|    3 |     1 |
|    1 |    -1 |
|    2 |     0 |
|    5 |     1 |
+------+-------+
6 rows in set (0.00 sec)

Para calcular el campo OP1, no hay problema (utilicé la forma alternativa del CASE-WHEN para búsqueda, no sé si sea compatible con el motor de BD's con la que trabajas, si no es así, puedes regresarlo a la forma que lo tienes con a=1, a=2, a=3):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> SELECT
    -> monto,
    ->   CASE a
    ->     WHEN 1 THEN (monto * 10)+(monto/51)
    ->     WHEN 2 THEN (monto + 28)+(monto*87)
    ->     WHEN 3 THEN (monto / 15)+(monto*1.158)
    ->     ELSE 0
    -> END AS OP1
    -> FROM Tabla;
+-------+----------+
| monto | OP1      |
+-------+----------+
|     1 |  10.0196 |
|     1 |      116 |
|     1 |   1.2247 |
|    -1 | -10.0196 |
|     0 |       28 |
|     1 |        0 |
+-------+----------+
6 rows in set (0.00 sec)

Ahora, para hacerlo con subconsultas, sería así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
mysql> SELECT
    ->   T.a, T.monto, T.OP1,
    ->   CASE WHEN T.OP1 > 0 THEN T.OP1*(-1) ELSE
    ->     CASE WHEN T.OP1 <0 THEN T.OP1/5
    ->       ELSE 0
    ->     END
    ->   END AS OP2
    -> FROM
    -> (
    ->   SELECT
    ->   a,
    ->   monto,
    ->   CASE a
    ->     WHEN 1 THEN (monto * 10)+(monto/51)
    ->     WHEN 2 THEN (monto + 28)+(monto*87)
    ->     WHEN 3 THEN (monto / 15)+(monto*1.158)
    ->     ELSE 0
    ->   END AS OP1
    ->   FROM Tabla) T;
+------+-------+----------+-------------+
| a    | monto | OP1      | OP2         |
+------+-------+----------+-------------+
|    1 |     1 |  10.0196 |    -10.0196 |
|    2 |     1 |      116 |   -116.0000 |
|    3 |     1 |   1.2247 |     -1.2247 |
|    1 |    -1 | -10.0196 | -2.00392157 |
|    2 |     0 |       28 |    -28.0000 |
|    5 |     1 |        0 |           0 |
+------+-------+----------+-------------+
6 rows in set (0.00 sec)

Al ejecutarse primero la subconsulta entonces la columna OP1 ya existe en la tabla "temporal" T, por lo tanto, puedes utilizarla sin ningún problema en el SELECT externo. la otra forma sería ANIDAR las condiciones para que se repitan los cálculos, es decir, hacer algo así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mysql> SELECT
    ->   a,
    ->   monto,
    ->   CASE a
    ->     WHEN 1 THEN (monto * 10)+(monto/51)
    ->     WHEN 2 THEN (monto + 28)+(monto*87)
    ->     WHEN 3 THEN (monto / 15)+(monto*1.158)
    ->     ELSE 0
    ->   END AS OP1,
    ->   CASE WHEN a = 1 and (monto * 10)+(monto/51) > 0    THEN ((monto * 10)+(monto/51))*(-1)    ELSE
    ->   CASE WHEN a = 1 and (monto * 10)+(monto/51) < 0    THEN ((monto * 10)+(monto/51))/5       ELSE
    ->   CASE WHEN a = 2 and (monto + 28)+(monto*87) > 0    THEN ((monto + 28)+(monto*87))*(-1)    ELSE
    ->   CASE WHEN a = 2 and (monto + 28)+(monto*87) < 0    THEN ((monto + 28)+(monto*87))/5       ELSE
    ->   CASE WHEN a = 3 and (monto / 15)+(monto*1.158) > 0 THEN ((monto / 15)+(monto*1.158))*(-1) ELSE
    ->   CASE WHEN a = 3 and (monto / 15)+(monto*1.158) < 0 THEN ((monto / 15)+(monto*1.158))/5    ELSE
    ->   0 END END END END END END AS OP2
    -> FROM Tabla;
+------+-------+----------+-------------+
| a    | monto | OP1      | OP2         |
+------+-------+----------+-------------+
|    1 |     1 |  10.0196 |    -10.0196 |
|    2 |     1 |      116 |        -116 |
|    3 |     1 |   1.2247 |     -1.2247 |
|    1 |    -1 | -10.0196 | -2.00392157 |
|    2 |     0 |       28 |         -28 |
|    5 |     1 |        0 |           0 |
+------+-------+----------+-------------+
6 rows in set (0.00 sec)

Ambas consultas regresarían el mismo resultado, sería cuestión de que evalúes cuál de las dos tiene un mejor desempeño.

Haz la prueba y nos comentas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 37
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

consulta SELECT, Hacer operaciones con el resultado de otra columna

Publicado por Jorge (19 intervenciones) el 18/04/2017 21:34:43
La BD está en MS-SQL Server 2014
la forma de subconsulta no se me había ocurrido (y ni sabía como se hacía ), estaba pensando en la segunda forma, anidando los campos, pero claro de esta forma me saldría una consulta enoooorme, probaré la forma de subconsulta a ver como me va
Gracias
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar