SQL - Comparar valores de dos o más campos/atributos pero contenidos un sólo registro

 
Vista:

Comparar valores de dos o más campos/atributos pero contenidos un sólo registro

Publicado por hector (5 intervenciones) el 26/03/2015 22:30:23
Supongamos esta tabla:

id_municipio / pp / psoe / podemos / ciudadanos

1 / 1000 / 500 / 1100 / 400
2 / 500 / 1000 / 200 / 800


Si por ejemplo quisiéramos saber que partido ganó en el municipio '1' tendremos que comparar cuál es el valor máximo de entre los campos 'pp', 'psoe', ... para un mismo registro.

Esto es posible hacerlo con una consulta??? (Hallar el valor max o min de valores contenidos en distintos campos pero de un mismo registro).
Ya luego, a partir de este select podríamos almacenar el nombre del partido más votado por ejemplo en otro campo con un update, no?
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
Imágen de perfil de Isaias
Val: 2.542
Oro
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

Comparar valores de dos o más campos/atributos pero contenidos un sólo registro

Publicado por Isaias (1921 intervenciones) el 26/03/2015 23:12:07
¿En que motor de base de datos?
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

Comparar valores de dos o más campos/atributos pero contenidos un sólo registro

Publicado por hector (5 intervenciones) el 26/03/2015 23:19:29
PostgreSQL/PostGIS
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: 806
Bronce
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

Comparar valores de dos o más campos/atributos pero contenidos un sólo registro

Publicado por leonardo_josue (1173 intervenciones) el 27/03/2015 16:51:48
Hola Hector:

No entiendo muy bien qué es lo que necesitas, pero veamos si esto es más o menos te puede servir.

De entrada, te comento que desde mi punto de vista, tu diseño de tablas está equivocado pero bueno, esa es otra cuestión, vayamos al asunto que te interesa. Antes que nada habría que responder a las siguientes preguntas:

1. ¿qué pasa si un partido no tiene ningún voto?, ¿el campo lo dejas con 0 o con null?
2. ¿qué pasa en el caso de que dos o más partidos tengan el mismo número de votos?, es decir, no se puede considerar un solo ganados.

Si entendí correctamente, para determinar sólo el partido ganador por municipio, puedes hacerlo de varias maneras. En este momento no tengo PostgreSQL para probar, pero la solución es SQL estandar, por lo que debería funcionar para cualquier DBMS, el ejemplo lo pongo en MySQL.

Supongamos que tienes tu tabla así:

1
2
3
4
5
6
7
8
9
10
11
mysql> SELECT * FROM tabla;
+--------------+------+------+---------+------------+
| id_municipio | pp   | psoe | podemos | ciudadanos |
+--------------+------+------+---------+------------+
|            1 | 1000 |  500 |    1100 |        400 |
|            2 |  500 | 1000 |     200 |        800 |
|            3 | 1500 |  600 |     400 |        200 |
|            4 |  400 |  300 |     250 |       1200 |
|            5 |  500 |  500 |     500 |        500 |
+--------------+------+------+---------+------------+
5 rows in set (0.00 sec)

Una solución sería comparar con un CASE-WHEN cada combinación posible, el problema es justamente con los empates... checa esta consulta:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> SELECT id_municipio,
    ->        CASE WHEN pp >= psoe       AND pp >= podemos      AND pp >= ciudadanos      THEN 'pp'      ELSE
    ->        CASE WHEN psoe >= pp       AND psoe >= podemos    AND psoe >= ciudadanos    THEN 'psoe'    ELSE
    ->        CASE WHEN podemos >= pp    AND podemos >= psoe    AND podemos >= ciudadanos THEN 'podemos' ELSE
    ->        CASE WHEN ciudadanos >= pp AND ciudadanos >= psoe AND ciudadanos >= podemos THEN 'ciudadanos'
    ->        END END END END partido_ganador,
    ->        CASE WHEN pp >= psoe       AND pp >= podemos      AND pp >= ciudadanos      THEN pp      ELSE
    ->        CASE WHEN psoe >= pp       AND psoe >= podemos    AND psoe >= ciudadanos    THEN psoe    ELSE
    ->        CASE WHEN podemos >= pp    AND podemos >= psoe    AND podemos >= ciudadanos THEN podemos ELSE
    ->        CASE WHEN ciudadanos >= pp AND ciudadanos >= psoe AND ciudadanos >= podemos THEN ciudadanos
    ->        END END END END votos_ganador
    -> FROM tabla;
+--------------+-----------------+---------------+
| id_municipio | partido_ganador | votos_ganador |
+--------------+-----------------+---------------+
|            1 | podemos         |          1100 |
|            2 | psoe            |          1000 |
|            3 | pp              |          1500 |
|            4 | ciudadanos      |          1200 |
|            5 | pp              |           500 |
+--------------+-----------------+---------------+
5 rows in set (0.00 sec)

Observa el último de los casos, los cuatro partidos tienen el mismo número de votos, por lo tanto depende de lo que respondas en la pregunta 1 si esta consulta es correcta o no. Otra manera para hacerlo sería cambiando tu modelo de BD's con UNION's, y a partir de esta estructura determinar el máximo número de votos para cada municipio, es decir, algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> SELECT id_municipio, MAX(votos_partido) max_votos FROM
    -> ( SELECT id_municipio, pp votos_partido FROM tabla
    ->   UNION
    ->   SELECT id_municipio, psoe votos_partido FROM tabla
    ->   UNION
    ->   SELECT id_municipio, podemos votos_partido FROM tabla
    ->   UNION
    ->   SELECT id_municipio, ciudadanos votos_partido FROM tabla) T
    -> GROUP BY id_municipio;
+--------------+-----------+
| id_municipio | max_votos |
+--------------+-----------+
|            1 |      1100 |
|            2 |      1000 |
|            3 |      1500 |
|            4 |      1200 |
|            5 |       500 |
+--------------+-----------+
5 rows in set (0.00 sec)

Una vez que tengas esta tabla, entonces faltaría cada id_municipio, para determinar qué partidos obtuvieron el número de votos máximo.

Ahora bien, volviendo a lo del modelo de tablas incorrecto... tú problema sería muy sencillo de resolver si en lugar de tener una sola tablas, manejas un catálogo de partidos y una tabla de relaciones, es decir, tener lo siguiente:

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
mysql> SELECT * FROM cat_partidos;
+------------+-------------+
| id_partido | descripcion |
+------------+-------------+
|          1 | pp          |
|          2 | psoe        |
|          3 | podemos     |
|          4 | ciudadanos  |
+------------+-------------+
4 rows in set (0.00 sec)
 
mysql> SELECT * FROM votos;
+--------------+------------+-------+
| id_municipio | id_partido | votos |
+--------------+------------+-------+
|            1 |          1 |  1000 |
|            1 |          2 |   500 |
|            1 |          3 |  1100 |
|            1 |          4 |   400 |
|            2 |          1 |   500 |
|            2 |          2 |  1000 |
|            2 |          3 |   200 |
|            2 |          4 |   800 |
+--------------+------------+-------+
8 rows in set (0.00 sec)

es decir, en lugar de manejar una columna por cada partido, manejas un registro. Este simple cambio, te simplificaría enormidades la consulta que planteas. Si es posible que hagas el cambio en tus tablas, hazlo, y con gusto te decimos cómo hacer la consulta de esta manera.

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

Comparar valores de dos o más campos/atributos pero contenidos un sólo registro

Publicado por hector (5 intervenciones) el 27/03/2015 18:01:49
Cierto, anoche lo estuve pensando y el principal inconveniente es ese...que la tabla no está normalizada, están malamente estructurados. Pero claro, el proveedor de los datos los da así y reestructurarlo sería una tarea bastante engorrosa creo, sobretodo si pensamos en que desde que se publiquen los datos queremos obtener la información del partido más votado en el menor tiempo posible. Se podría hacer un programita que lea y reestructure los datos...pero ahora te comento la otra solución (más sencilla) que he pensado relacionada con esto último.

Coincido contigo en que lo suyo sería tener una tabla (lista controlada) de partidos, otra de municipios (con un atributo pensado para el nombre del ganador también) y como la relación entre ellas sería N:M, pues una tabla resultante de la relación con las FK y el número de votos como atributo de la relación.

Lo otro que comentas respecto de los nulos y los empates, pues, creo que en vez de dejar un guión o un null sería mejor poner un cero como valor numérico de cara a ordenar los valores sin problemas. Lo de los empates, cierto, sería una 'anomalía'... en la que no había reparado por ser poco frecuente que pase. Habría que estudiarlo.


Y bueno, la otra solución que he estado pensando es... xDD como se trata de una tabla no normalizada creo que no me voy a volver muy loco y simplemente voy a tomar como formato de partida un CSV, voy a olvidarme de cargarlo en un SGBD y de las consultas y voy a hacer un programita (en python que es el lenguaje que controlo) que:
-vaya leyendo cada línea del csv con un bucle.
-transforme los valores en tuplas/listas a partir de las cuales podría saber cuál es el valor máximo, seleccionarlo y hacerle demás perrerías.
-con ayuda de una tupla/lista de referencia con sólo nombres de partidos saber, a partir de la posición que ocupe el valor máximo en su tupla, a qué partido corresponde.
-y que almacene el nombre, por ejemplo, en un nuevo fichero junto al nombre del municipio (pudiendo escribir también los votos de los partidos en el mismo si creemos volver a necesitarlos).

Una solución un poco de andar por casa, pero con la que conseguiríamos el objetivo buscado empleando poquito tiempo... qué opinas??

[No lo había dicho pero, el querer conocer el partido más votado es simplemente para crear un mapa web (un pequeño SIG) que pinte los municipios por categorías (rojo-psoe, azul-pp,...) y tener una visión rápida e intuitiva de los resultados electorales... por cierto, no formo parte de la estructura de ningún partido, ni siquiera trabajo en prensa xD ... es más bien 'un reto personal' :) ]
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