Załóżmy, że mam grę, w którą może grać 2, 3 lub 4 graczy. Śledzę taką grę w mojej bazie danych (MySQL 5.1) w trzech tabelach, podanych poniżej. Mam nadzieję, że pola są oczywiste:Lewe łączenie tego samego stołu wiele razy
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);
[Dwa razy śledzone w tabeli gry są czas rozpoczęcia i zakończenia]
Oto niektóre fikcyjne dane do wypełnienia tabel:
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);
teraz muszę przedstawić sprawozdanie w następującym formacie:
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]
Oznacza to, raport, który pokazuje wszystkich graczy, którzy grali w grę w tym samym rzędzie. Muszę również swoje wyniki i niektóre inne informacje z tabeli użytkowników, ale to jest faza 2. :-)
zacząłem z tym:
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
To daje mi wszystkie gry, w których zostały zajęte wszystkie cztery miejsca (tj. tylko identyfikator gry 3 w powyższych danych fikcyjnych). Ale to tylko podzbiór danych, których potrzebuję.
To jest moja druga próba:
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
To daje mi 14 wiersze z powyższych danych manekina. Starałem się wyeliminować jedno źródło błędu poprzez zakotwiczenie UG1 wejściem do najniższego UID gracza:
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
Teraz jestem w dół do 9 wierszy, ale mam jeszcze wiele fałszywych danych. Widzę problem - na przykład w grze 3, z ug1 zakotwiczonym dla użytkownika 102, wciąż jest trzech graczy, na których można zakotwić ug2. I tak dalej. Ale nie mogę znaleźć sposobu na rozwiązanie tej zagadki - w jaki sposób mogę ostatecznie uzyskać zapytanie, które wyświetli 4 wiersze z graczami we właściwej kolejności i liczbie?
To wydaje mi się, że powinienem rozwiązać problem w innych kontekstach. Doceniam wszelką pomoc tutaj.
Zdecydowanie zalecamy, aby * nie * miesza składnię ',' i 'JOIN'. Po prostu użyj 'JOIN', to nie jest już 20 lat nieaktualne ... – MatBailie