MySQL - Querie no tipico

 
Vista:

Querie no tipico

Publicado por daniel (3 intervenciones) el 02/06/2017 03:37:17
Hola amigos, espero alguien pueda ayudarme. Fijense que tengo dos tablas. Y lo quiero es sacar informacion de ambas pero en una tabla solo saco informacion de una fila y en la otra obtengo informacion de 2 filas:

Tabla 1: Football

stage ronda id next_stage
2 -------1--- 456----------34

----------------------------------------

Tabla 2: Puntuacion

stage jugador id_jugador puntuacion ganador
2 -----------Mesi---------- 45-------------------3---------------1
2-----------Ronaldo-------89 ----------------- 8---------------- 0


El problema que tengo es que al hacer el querie me repite la informacion de la primer tabla varias veces (en este caso 2 veces) y no quiero que suceda esto:

[[stage:2, id:456, jugador:mesi, ganador:1] [stage:2, id:456, jugador:ronaldo, ganador:0]]

Alguien sabe como hacer la querie correctamente en este caso? o es imposible mas que nada lo hago para no tener que hacer dos peticiones separadas.

Esta es la querie que tengo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'SELECT'    => f.stage,f.id,p.jugador,p.ganador',
                    'FROM'      => array(
                        phpbb_football => 'f',
                        phpbb_puntuacion => 'p',
                    ),
                    'WHERE'     => "f.id =" . $id .
                                    " AND f.stage = p.stage"
                  );
    $sql = $this->db->sql_build_query('SELECT', $sql_ary);
            $result = $this->db->sql_query($sql);

while($row = $this->db->sql_fetchrow($result)).....



Gracias de antemano :)
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: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Querie no tipico

Publicado por leonardo_josue (414 intervenciones) el 02/06/2017 15:59:27
Hola Daniel:

la consulta que planteas está lejos de ser imposible, en realidad hay muchas formas de resolverla, aunque dependerá completamente de cómo tengas tu información.

Para el ejemplo, voy a hacer dos suposiciones:

-> primero, que tu relación siempre es 1 a 2 es decir, por cada registro en tu tabla FOOTBALL existen 2 y SOLO DOS registros en tu tabla puntuación.
-> que los ID_JUGADOR son consecutivos Y NO SE REPITEN...

El primer paso sería NUMERAR LOS REGISTROS DE TU TABLA PUNTUACIÓN, para asignarles valores de 1 y 2 (o primero y segundo)... de hecho, si pudieras desde tu lógica de negocio guardar estos valores, la consulta se haría más simple... voy a tomar estos datos de ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> SELECT * FROM football;
+-------+-------+------+------------+
| stage | ronda | id   | next_stage |
+-------+-------+------+------------+
|     2 |     1 |  456 |         34 |
|     3 |     1 |  457 |         35 |
+-------+-------+------+------------+
2 rows in set (0.00 sec)
 
mysql> SELECT * FROM puntuacion;
+-------+---------+------------+------------+---------+
| stage | jugador | id_jugador | puntuacion | ganador |
+-------+---------+------------+------------+---------+
|     2 | Mesi    |         45 |          3 |       1 |
|     2 | Ronaldo |         89 |          8 |       0 |
|     3 | Zidane  |         91 |          9 |       1 |
|     3 | Totti   |         72 |          8 |       0 |
+-------+---------+------------+------------+---------+
4 rows in set (0.00 sec)

hay muchas formas de numerar registros, una de las más simples es utilizar subconsultas con COUNT(), por lo tanto puedes hacer algo así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> SELECT P1.*, (SELECT COUNT(1)
    ->               FROM puntuacion P2
    ->               WHERE P1.stage = P2.stage
    ->                     AND P1.id_jugador >= P2.id_jugador) posicion
    -> FROM puntuacion P1
    -> ORDER BY P1.stage, posicion;
+-------+---------+------------+------------+---------+----------+
| stage | jugador | id_jugador | puntuacion | ganador | posicion |
+-------+---------+------------+------------+---------+----------+
|     2 | Mesi    |         45 |          3 |       1 |        1 |
|     2 | Ronaldo |         89 |          8 |       0 |        2 |
|     3 | Totti   |         72 |          8 |       0 |        1 |
|     3 | Zidane  |         91 |          9 |       1 |        2 |
+-------+---------+------------+------------+---------+----------+
4 rows in set (0.00 sec)

Observa que lo único que hice es agregar una columna para numerar los registros por orden de id_jugador. Ahora, esta consulta la puedes utilizar para hacer un DOBLE INNER JOIN, filtrando por posición... suena más complicado de lo que es, quedarí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
mysql> SELECT f.stage, T1.id_jugador, T1.jugador, T1.ganador, T2.id_jugador, T2.
jugador, T2.ganador
    -> FROM
    -> football F
    -> INNER JOIN
    -> ( SELECT P1.*, (SELECT COUNT(1)
    ->                 FROM puntuacion P2
    ->                 WHERE P1.stage = P2.stage
    ->                       AND P1.id_jugador >= P2.id_jugador) posicion
    ->   FROM puntuacion P1
    ->  ) T1 ON T1.stage = F.stage AND T1.posicion = 1
    ->  INNER JOIN
    -> ( SELECT P1.*, (SELECT COUNT(1)
    ->                 FROM puntuacion P2
    ->                 WHERE P1.stage = P2.stage
    ->                       AND P1.id_jugador >= P2.id_jugador) posicion
    ->   FROM puntuacion P1
    ->  ) T2 ON T2.stage = F.stage AND T2.posicion = 2;
+-------+------------+---------+---------+------------+---------+---------+
| stage | id_jugador | jugador | ganador | id_jugador | jugador | ganador |
+-------+------------+---------+---------+------------+---------+---------+
|     2 |         45 | Mesi    |       1 |         89 | Ronaldo |       0 |
|     3 |         72 | Totti   |       0 |         91 | Zidane  |       1 |
+-------+------------+---------+---------+------------+---------+---------+
2 rows in set (0.02 sec)

Observa que la subconsulta ES EXACTAMENTE LA MISMA, pero se ponen ALIAS DISTINTOS y en la condición ON se filtra primero para posicion = 1 y después para posición = 2.

Esta es una forma de hacerlo, no es ni de broma la mejor forma de hacerlo, pero creo que te puede ayudar a pensar de manera distinta y buscar otras alternativas.

Dale un vistazo y si tienes dudas lo comentas y lo vemos.

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

Querie no tipico

Publicado por daniel (3 intervenciones) el 02/06/2017 20:41:03
Gracias por responder. Si de hecho en la tabla puntuacion ya tengo el campo posicion nada mas que uso 0 y 1. Solo que no lo puse aqui xD. Aunque no logro entender del todo el querie que formulaste. No habra alguna forma mas sencilla? :/ Disculpa no soy tan experimentado en el mysql. Entiendo que con cada unno filtras la informacion del player 1 y el player 2 pero lo que no entiendo es el codigo,
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: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Querie no tipico

Publicado por leonardo_josue (414 intervenciones) el 02/06/2017 23:35:54
Hola de nuevo Daniel:

1
¿No habra alguna forma mas sencilla?

tal como te dije en mi post, hay muchas formas de hacer esto, pero depende de cómo tienes organizada tu información...

gran parte de la complejidad del problema como te comenté es en realidad por tener que numerar los registros, lamentablemente aquí no somos adivinos como para saber qué información adicional tienes en tus tablas. si dices que ya tienes numerados los registros, entonces la consulta puede simplificarse bastante...

Trataré de explicar mejor la lógica con otro ejemplo.

Supongamos que tienes dos tablas así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> SELECT * FROM equipos;
+-----------+-------------+
| id_equipo | descripcion |
+-----------+-------------+
|         1 | Real Madrid |
|         2 | Juventus    |
|         3 | Barcelona   |
+-----------+-------------+
3 rows in set (0.00 sec)
 
mysql> SELECT * FROM partidos;
+------------+-----------------+---------------------+
| id_partido | id_equipo_local | id_equipo_visitante |
+------------+-----------------+---------------------+
|          1 |               1 |                   2 |
|          2 |               1 |                   3 |
|          3 |               2 |                   3 |
+------------+-----------------+---------------------+
3 rows in set (0.00 sec)

donde los campos id_equipo local y id_equipo visitante corresponden al id_equipos, es decir, tienes una doble referencia hacia la misma tabla (esto es más o menos lo mismo


ahora, imagina que quieres saber el nombre de los equipos que se van a enfrentar en cada partido, entonces, primero obtienes el nombre del equipo local, con un simple JOIN:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SELECT
    ->   partidos.id_partido,
    ->   partidos.id_equipo_local,
    ->   equipos.descripcion,
    ->   partidos.id_equipo_visitante
    -> FROM
    ->   partidos
    -> INNER JOIN equipos ON id_equipo_local = equipos.id_equipo;
+------------+-----------------+-------------+---------------------+
| id_partido | id_equipo_local | descripcion | id_equipo_visitante |
+------------+-----------------+-------------+---------------------+
|          1 |               1 | Real Madrid |                   2 |
|          2 |               1 | Real Madrid |                   3 |
|          3 |               2 | Juventus    |                   3 |
+------------+-----------------+-------------+---------------------+
3 rows in set (0.00 sec)

pero cómo haces para obtener la descripción del equipo visitante??? pues haces un doble JOIN,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql> SELECT
    ->   partidos.id_partido,
    ->   partidos.id_equipo_local,
    ->   A.descripcion LOCAL,
    ->   partidos.id_equipo_visitante,
    ->   B.descripcion visitante
    -> FROM
    ->   partidos
    -> INNER JOIN equipos A ON id_equipo_local = A.id_equipo
    -> INNER JOIN equipos B ON id_equipo_visitante = B.id_equipo;
+------------+-----------------+-------------+---------------------+-----------+
| id_partido | id_equipo_local | LOCAL       | id_equipo_visitante | visitante |
+------------+-----------------+-------------+---------------------+-----------+
|          1 |               1 | Real Madrid |                   2 | Juventus  |
|          2 |               1 | Real Madrid |                   3 | Barcelona |
|          3 |               2 | Juventus    |                   3 | Barcelona |
+------------+-----------------+-------------+---------------------+-----------+
3 rows in set (0.00 sec)

Observa que aunque se trata de la misma tabla, se manejan DOS ALIAS A y B, de manera que se pueden tratar como si fueran dos tablas distintas... Esta es la misma idea de lo que hago en la consulta...

espero que haya quedado un poco más claro así.

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

Querie no tipico

Publicado por daniel (3 intervenciones) el 04/06/2017 00:35:55
ahh ok. Disculpa como la manera de declarar la querie es diferente me cuesta entenderlo mas. Pero entonces puedo hacer algo como esto?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'SELECT'    => f.stage,f.id,p.jugador,p.ganador,b.jugador,b.ganador',
                    'FROM'      => array(
                        phpbb_football => 'f',
                        phpbb_puntuacion => 'p',
                        phpbb_football => 'a',
                        phpbb_puntuacion => 'b',
                    ),
                    'WHERE'     => "f.id =" . $id .
                                    " AND f.stage = p.stage
                                     AND a.stage = a.stage"
                  );
    $sql = $this->db->sql_build_query('SELECT', $sql_ary);
            $result = $this->db->sql_query($sql);

while($row = $this->db->sql_fetchrow($result)).....
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