Supongamos que tengo un juego que puede jugar 2, 3 o 4 jugadores. Rastreo tal juego en mi base de datos (MySQL 5.1) en tres tablas, que figuran a continuación. Tengo la esperanza de que los campos no necesitan explicación:Unir a la izquierda la misma mesa varias veces
create table users (id int, login char(8));
create table games (id int, stime datetime, etime datetime);
create table users_games (uid int, gid int, score int);
[Las dos veces seguidas en la tabla de juegos son el tiempo de inicio y final]
aquí tienes datos ficticios para rellenar las tablas:
insert into games values
(1, '2011-12-01 10:00:00', '2011-12-01 13:00:00'),
(2, '2011-12-02 11:00:00', '2011-12-01 14:00:00'),
(3, '2011-12-03 12:00:00', '2011-12-01 15:00:00'),
(4, '2011-12-04 13:00:00', '2011-12-01 16:00:00');
insert into users_games values
(101, 1, 10),
(102, 1, 11),
(101, 2, 12),
(103, 2, 13),
(104, 2, 14),
(102, 3, 15),
(103, 3, 16),
(104, 3, 17),
(105, 3, 18),
(102, 4, 19),
(104, 4, 20),
(105, 4, 21);
Ahora, necesito para producir un informe en el siguiente formato:
gid p1 p2 p3 p4 started ended
1 101 102 [g1] [g1]
2 101 103 104 [g2] [g2]
3 102 103 104 105 [g3] [g3]
4 102 104 105 [g4] [g4]
es decir, un informe que muestra todos los jugadores que jugaron un juego en la misma fila. También necesito sus puntuaciones y alguna otra información de la tabla de usuarios, pero que es la fase 2. :-)
empecé con esto:
select g.id, g.stime, g.etime, ug1.uid, ug2.uid, ug3.uid, ug4.uid
from games g, users_games ug1, users_games ug2, users_games ug3, users_games ug4
where
g.id = ug1.gid and
ug1.gid = ug2.gid and
ug1.uid < ug2.uid and
ug2.gid = ug3.gid and
ug2.uid < ug3.uid and
ug3.gid = ug4.gid and
ug3.uid < ug4.uid
Esto me todos los juegos en los que se ocuparon los cuatro asientos da (es decir, solo el juego ID 3 en los datos ficticios anteriores). Pero eso es solo un subconjunto de los datos que necesito.
Este es mi segundo intento:
select g.id, g.stime, g.etime, ug1.uid, ug2.uid,
ifnull(ug3.uid, ''), ifnull(ug4.uid, '')
from (games g, users_games ug1, users_games ug2)
left join users_games ug3 on ug2.gid = ug3.gid and ug2.uid < ug3.uid
left join users_games ug4 on ug3.gid = ug4.gid and ug3.uid < ug4.uid
where
g.id = ug1.gid and
ug1.gid = ug2.gid and
ug1.uid < ug2.uid
Esto me da 14 filas con los datos ficticios anteriores. He intentado eliminar una fuente de error mediante el anclaje UG1 a la entrada para el jugador de menor-UID:
select g.id, g.stime, g.etime, ug1.uid, ug2.uid,
ifnull(ug3.uid, ''), ifnull(ug4.uid, '')
from
(games g, users_games ug1, users_games ug2,
(select gid as g, min(uid) as u from users_games group by g) as xx
)
left join users_games ug3 on ug2.gid = ug3.gid and ug2.uid < ug3.uid
left join users_games ug4 on ug3.gid = ug4.gid and ug3.uid < ug4.uid
where
g.id = xx.g and
ug1.uid = xx.u and
g.id = ug1.gid and
ug1.gid = ug2.gid and
ug1.uid < ug2.uid
Ahora estoy abajo a 9 filas, pero todavía tengo un montón de datos espurios. Puedo ver el problema, por ejemplo, en el juego 3, con ug1 anclado al usuario 102, todavía hay tres jugadores a los que se puede anclar ug2. Y así. Pero no puedo encontrar una manera de resolver este enigma: ¿cómo puedo finalmente lograr una consulta que genere 4 filas con los jugadores en el orden y número correctos?
Esto me parece debería ser un problema resuelto en otros contextos. Apreciaremos toda la ayuda aquí.
Yo les aconsejamos a * no * mezcla la sintaxis ',' y 'JOIN'. Simplemente use 'JOIN', no está 20 años fuera de fecha ... – MatBailie