ITnetwork Flashka zdarma C# týden
Akce! Pouze tento týden sleva až 80 % na kurzy C# .NET. Lze kombinovat s akcí 50 % bodů navíc na prémiový obsah!
Brno? Vypsali jsme pro vás nové termíny školení Základů programování a OOP v Brně!
Avatar
Petr Langer
Člen
Avatar
Petr Langer:27. dubna 18:30

Mám tyto tabulky
USERS(user_id,...)
LEVELS(level_id, starting_phase_fk,­...)
PHASES(phase_id,­...)
PROGRESS(progres­s_id, user_fk, level_fk, phase_fk)
(reference jsou snad zřejmé)
Jde o to, že uživatel může hrát v různých levelech, přičemž každý level má různé fáze ve kterých se uživatel může nacházet. V tabulce PROGRESS se potom ukládá v jaké fázi uživatel v daném levelu skončil naposledy, pokud level ještě nehrál, tak v tabulce PROGRESS neexistuje záznam.
To by bylo tak na úvod, aby bylo jasné jak databáze má fungovat.
Já potřebuju poradit, jak složit SQL dotaz, který by mi vrátil pro konkrétního uživatele jeho postup ve všech levelech (phase_id). Tzn. počet vrácených řádků bude odpovídat počtu řádků v tabulce LEVELS a pokud pro daného uživatele a konkrétní level nebude existovat záznam v tabulce PROGRESS, tak se vrátí NULL

Zkusil jsem: Zkoušel jsem něco jako:

SELECT progress.phase_fk, levels.*
FROM progress
LEFT JOIN levels ON levels.level_id = progress.level_fk
WHERE users_user_id = 1

To mi vrátí jen levely, které už uživatel hrál, ale já tam potřebuju i ty, které ještě nehrál.

Chci docílit: Výsledek by mohl vypadat nějak takhle

user_id level_id starting_phase_fk phase_fk
1 1 1 null
1 2 5 5

Level s id 1 ještě nehrál a v levlu s id 2 je ve fázi 5 (počáteční fázi)
Možná mám blbě navrženou databázi, za každou radu budu vděčný.

 
Odpovědět 27. dubna 18:30
Avatar
Odpovídá na Petr Langer
Michal Štěpánek:27. dubna 21:41

Zkus použít "OUTER JOIN", ten ti vrátí všechny výsledky i z tabulky, kde "není záznam"...

Nahoru Odpovědět 27. dubna 21:41
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Petr Langer
Člen
Avatar
Odpovídá na Michal Štěpánek
Petr Langer:28. dubna 9:15

To mi fungovalo jen když jsem tam nedal tu podmínku WHERE, ale pak mi to vrátilo výsledky pro všechny uživatele. Každopádně už jsem našel řešení. Udělal jsem select všech levelů a pak i select všech progresů uživatele a výsledky jsem najoinoval právě outer joinem. Musely tam být dva selecty v jednom dotazu jinak mi to vracelo jen levely, u kterých měl uživatel nějaký progres

 
Nahoru Odpovědět 28. dubna 9:15
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:29. dubna 9:36

Musis to rozebrat na elementarni informace.
Ono, pojmenovani tabulek take neni stastne. Osobne davam jmena tak, k jake hlavni tabulce se vazou. Pr
osoby, osoby_adresa, osoby_...

USERS(user_id,...)
USERS(id_user,...) -- nazev sloupce davam id, doplnujici informace je, ze je to id_useri. Opacne pojmenovani mi prijde nelogicke. Chapu, chces rici, ze tabulka osoby, sloupec id. Ale nelogice :)

U tech ostatnich tabulek nemas uvedena indexy. Takze se z toho neda nic vycarovat. Mozna tam zadne nemas :) Kdyz se mi to nechce vypisovat, tak na forko pouzivam takovyto zapis. Jenom se domnivam, ze by to melo vypadat nejak takto

USERS(id_user, data)
LEVELS(id_level, data nejake info)
user_level (id, id_user, id_level) -- vazebni, id nema vztah k jinemu id z jine tabulky, proto tam neni id_neco
user_PROGRESS(id, id_progress, id_user, id_level, id_phase, data)
PHASES(id_phase,...)

Pokud jsem to odhadl dobre, tak jedine, cemu nerozumim je starting_phase_fk. V user_PROGRESS uz jedenkrat id_level je. To bys musel asi vice objasnit fungovani level - progress - user

user_id         level_id        starting_phase_fk       phase_fk

Vetsinu tech informaci mas v user_PROGRESS, takze, k ni asi budes vazat ostatni.

SELECT sloupce FROM user_PROGRESS LEFT JOIN user... LEFT JOIN levels, ... GROUP BY nebo neco, treba
Editováno 29. dubna 9:37
 
Nahoru Odpovědět 29. dubna 9:36
Avatar
Petr Langer
Člen
Avatar
Petr Langer:29. dubna 12:35

U pojmenování tabulek a sloupců si jsem vědom, že to není ideální, ale jsem na to zvyklý, tak to tak používám.
Sloupec starting_phase_fk byl cizí klíč na počáteční fázi úrovně (abych věděl, kterou fází úroveň začíná), ale to je teď nepodstatné.
Přidal jsem obrázek schéma osekané databáze jen na to nejnutnější. Dotaz, který potřebuju by mi měl vráti seznam všech úrovní a pokud už má uživatel v nějaké úrovni nějaký progres, tak se vrátí i id fáze, ve které naposledy skončil. Pokud level ještě nehrál, tak vrátí místo id fáze null.
Tabulka progres je řešena tak, že pokud uživatel nějaký level ještě nehrál, tak tam neexistuje žádný záznam.

SELECT progress.user_iduser, level.idlevel, progress.phase_idphase FROM level
LEFT JOIN progress ON level.idlevel = progress.phase_level_idlevel
WHERE progress.user_iduser = 1

tohle mi vrací jenom levely, kde už má uživatel nějaký progres (joiny jsem zkoušel všechny druhy)
db

Editováno 29. dubna 12:38
 
Nahoru Odpovědět 29. dubna 12:35
Avatar
Odpovídá na Petr Langer
Michal Štěpánek:29. dubna 13:22

Myslím, že jsi při tom zkoušení JOINů musel dělat něco špatně, protože LEFT OUTER JOIN nebo RIGHT OUTER JOIN na to musí fungovat...

Nahoru Odpovědět 29. dubna 13:22
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Petr Langer
Člen
Avatar
Odpovídá na Michal Štěpánek
Petr Langer:29. dubna 14:21

Zkoušel jsem opravdu všechny (i ty které si myslím, že stejně mají stejný význam). Kromě JOINu jsem nechal dotaz tak, jak jsem ho uváděl naposledy. Podle mě tam dělá problém ta podmínka WHERE, protože když ji tam nedám, tak se to najoinuje tak jak bych potřeboval, ale jsou tam zase řádky s uživatelema, který nechci

 
Nahoru Odpovědět 29. dubna 14:21
Avatar
Petr Langer
Člen
Avatar
Petr Langer:29. dubna 14:34

Tak už jsem na to asi přišel

SELECT progress.user_iduser, level.idlevel, progress.phase_idphase FROM level
LEFT JOIN progress ON level.idlevel = progress.phase_level_idlevel AND progress.user_iduser = 1

Podmínka musela být v tom joinu a ne samostatně jako WHERE

Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět 29. dubna 14:34
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 8 zpráv z 8.