Autor | Zpráva | ||
---|---|---|---|
holi Profil |
Zdravím,
omlouvám se za název tématu, ale můj problém nejde specifikovat jednou větou. Mám seznam přiřazených učitelů k předmětům pro daného žáka. Každý žák má ale právo na jeden volitelný předmět z X volitelných předmětů v daném zaměření. Chci ze selectboxu vyřadit volitelné předměty pokud žák již má jeden z volitelných předmětů z jednoho zaměření přiřazen. Přiřazení v databázi se provádí přes tabulku rozvrh kde je přiznak(bool) přiřazení pak id učitele, žáka a předmětu. Pomocí relací si vytáhnu z DB předměty, které se žáku mohou přiřadit(podle zaměření které žák má). Nyní potřebuji zjistit zda má žák již přiřazen volitelný předmět a pokud ano pak odstranit ostatní volitelné předměty z toho co jsem vytáhl v minulé větě(bacha! v zaměření jsou i povinné předměty). A zde jsem se zasekl. Prozatím to dělám v PHP přes dva dotazy a foreachem projíždím pole a odstranuji zbytek volitelných předmětů takto. Jenže to se mi nezdá jako správný způsob a chtěl bych to provést skrz SQL. Takto teď vypadá funkce pro získání předmětů, kterou jsem popsal a ze které bych chtěl udělat jeden SQL dotaz: <?php $available = $this->connection->query('SELECT [focuses].[focus], [subjects].[id], [subjects].[name], [subjects].[shortcut], [subjects].[level], [subjects].[class], [subjects].[hours], [subjects].[description], [subjects].[materials], [subjects].[optional] FROM [students] INNER JOIN [inclusions] ON [students].[id] = [inclusions].[student] INNER JOIN [focuses] ON [inclusions].[focus] = [focuses].[id] INNER JOIN [subjects] ON [focuses].[id] = [subjects].[focus] AND [inclusions].[level] = [subjects].[level] AND [inclusions].[class] = [subjects].[class] WHERE [students].[id] = %i AND [subjects].[id] NOT IN(SELECT [subject] FROM [schedule] WHERE [student] = [students].[id] AND [assignment] = "1") GROUP BY [subjects].[id]', $id)->fetchAll(); $control = $this->connection->query('SELECT [subject] FROM [schedule] JOIN [subjects] ON [schedule].[subject] = [subjects].[id] AND [student] = %i AND [assignment] = "1" AND [optional] = "1"', $id)->fetchAll(); if(count($control)){ foreach($available as $key => $subject){ if($subject->optional) unset ($available[$key]); } } return $available; ?> BTW používám DIBI |
||
tiso Profil |
#2 · Zasláno: 4. 9. 2013, 22:06:17
Prečo to neurobíš naopak? Zistíš, či má priradený voliteľný predmet a podľa toho vyberieš buď všetky predmety, alebo len povinné.
|
||
holi Profil |
#3 · Zasláno: 4. 9. 2013, 23:52:22
tiso:
Můžete dat nějaký příklad nemůžu si nějak představit jak to provést |
||
Kajman Profil |
Zjistíte, zda dotaz z řádku 17 najde nějaký řádek. V tom případě přidáte do dotazu z řádku 2 podmínku např. do where, že optional není jedna nebo je null.
|
||
holi Profil |
#5 · Zasláno: 5. 9. 2013, 08:36:59
Zřejmě jste me nepochopili. Já to všechno chci v jednom sql. Kdybych to chtěl na vice tak to zřejmě udělám i takhle, ale to pro me není řešení.
|
||
tiso Profil |
#6 · Zasláno: 5. 9. 2013, 09:35:39
holi: čo je zlé na dvoch dotazoch do DB?
|
||
holi Profil |
Rychlost a vytížení serveru, kvůli tomu se vymysleli relační spojení tabulek.
EDIT:// Prostě se snažím nahnat každou milisekundu a byte v paměti EDIT://Nehledě na to že funkci chci později použít na vypsání všech žáků, kteří nemají přiřazený nějaký předmět a v tomto případě by to znamenalo co žák to dotaz a že těch žáků bude :) |
||
Alphard Profil |
#8 · Zasláno: 5. 9. 2013, 13:21:05
Co třeba algoritmus v [#4] napsat do where pomocí poddotazu?
where (select count(*) ...) = 0 or (optional != 1 or optional is null) |
||
Kajman Profil |
#9 · Zasláno: 5. 9. 2013, 17:51:14
Snad by šlo i něco takového...
SELECT [focuses].[focus], [subjects].[id], [subjects].[name], [subjects].[shortcut], [subjects].[level], [subjects].[class], [subjects].[hours], [subjects].[description], [subjects].[materials], [subjects].[optional] FROM [students] INNER JOIN [inclusions] ON [students].[id] = [inclusions].[student] INNER JOIN [focuses] ON [inclusions].[focus] = [focuses].[id] INNER JOIN [subjects] ON [focuses].[id] = [subjects].[focus] AND [inclusions].[level] = [subjects].[level] AND [inclusions].[class] = [subjects].[class] LEFT JOIN [schedule] ON [students].[id] = [schedule].[student] AND [subjects].[id] = [schedule].[subject] AND [schedule].[assignment] = "1" LEFT JOIN [subjects] AS [subjects2] ON [subjects].[focus] = [subjects2].[focus] AND [subjects].[level] = [subjects2].[level] AND [subjects].[class] = [subjects2].[class] AND [subjects].[optional] = "1" AND [subjects2].[optional] = "1" LEFT JOIN [schedule] AS [schedule2] ON [students].[id] = [schedule2].[student] AND [subjects2].[id] = [schedule2].[subject] AND [schedule2].[assignment] = "1" WHERE [students].[id] = %i AND [schedule].[subject] IS NULL AND [schedule2].[subject] IS NULL GROUP BY [subjects].[id] Ale tipuji, že to nebude přínos ani v rychlosti ani v čitelnosti kódu oproti řešení v [#2]. |
||
Časová prodleva: 4 dny
|
|||
holi Profil |
#10 · Zasláno: 9. 9. 2013, 09:02:09
Tak jsem to vyřešil, tady je funkční skript.
query('SELECT [focuses].[focus], [subjects].[id], [subjects].[name], [subjects].[shortcut], [subjects].[level], [subjects].[class], [subjects].[hours], [subjects].[description], [subjects].[materials], [subjects].[optional] FROM [students] INNER JOIN [inclusions] ON [students].[id] = [inclusions].[student] INNER JOIN [focuses] ON [inclusions].[focus] = [focuses].[id] INNER JOIN [subjects] ON [focuses].[id] = [subjects].[focus] AND [inclusions].[level] = [subjects].[level] AND [inclusions].[class] = [subjects].[class] WHERE [students].[id] = %i',$id,' AND [subjects].[id] NOT IN(SELECT [subject] FROM [schedule] WHERE [student] = [students].[id] AND [assignment] = "1") AND ((SELECT COUNT([sch].[id]) FROM [schedule] AS [sch] JOIN [subjects] AS [s] ON [sch].[subject] = [s].[id] WHERE [sch].[student] = [students].[id] AND [sch].[assignment] = "1" AND [s].[optional] = "1" AND [inclusions].[class] = [s].[class] AND [inclusions].[level] = [s].[level] AND [inclusions].[focus] = [s].[focus]) = 0 OR subjects.optional = 0) GROUP BY [subjects].[id] ORDER BY [focus]') |
||
Časová prodleva: 11 let
|
0