Autor Zpráva
Tori
Profil
Pěkný večer,
mohli byste mi, prosím, poradit, jestli by bylo lepší změnit databázi, nebo logiku ukládání dat?

Jde o systém na zapisování se na konzultace/zkoušky apod., elektronická verze papíru na dveřích od kabinetu. Lektor vypíše 1+ termínů (= konkrétní den, od-do) ke každé „události“ a zadá délku jednotlivých políček rozpisu („rezervací“). Na každý čas se může přihlásit 1+ studentů, ale každý student si smí rezervovat pouze jeden čas v rámci jedné události.

Takže když např.lektor vypíše jen dva termíny, stejný den ráno a v poledne, do DB jdou data asi ve tvaru:
id_události | id_termínu | datum    | začátek | id_studenta
------------------------------------------------------------
      1     |     1      | 5.1.2011 |  08:00  |     0      |    * neuvedené hodnoty se opakují
      *     |            |          |  08:20  |     0      |
            |            |          |  08:40  |     0      |
            |            |          |  09:00  |     0      |
            |     2      | 5.1.2011 |  12:00  |     0      |
            |            |          |  12:20  |     0      |
            |            |          |  12:40  |     0      |
------------------------------------------------------------

Tzn. musím uložit všechny časy pro všechny termíny. Datum i čas jsem dala do samostatných tabulek, vazba přes ID, vkládám INSERT IGNORE. Řešení přes opakované INSERT...SELECT je dost ošklivé (a asi i pomalé). Kdybych místo ID ukládala přímo ty časy a datumy, ušetřím si sice práci při vytvoření/editaci termínů, ale za cenu značné redundance. Na druhou stranu není pravděpodobné, že by někdo mohl chtít editovat jeden časový údaj v celé DB.

Bylo by tedy lepší
* změnit DB, udělat méně a jednodušších dotazů i za cenu opakování dat, anebo
* snažit se změnit logiku ukládání (a jak?), aby bylo alespoň méně dotazů ?
Budu moc ráda za navedení správným směrem.
marcus33cz
Profil
Ahoj,

no to by bylo asi na složitější vysvětlování, ale v tomhle bych vážně viděl chybu logiky - špatně navržená databáze.

* neuvedené hodnoty se opakují ???
Ale to je základní princip identifikátoru - cílem je, aby se ten sloupec ID (v tvém případě id_termínu a id_události) NEOPAKOVAL. Právě proto má většinou vlastnost AUTO INCREMENT (a mimochodem se i používá tak, aby se na ID vymazaných záznamů už nic nevkládalo).

V databázi to takhle nemá být, což se dá poznat už z toho, že se jí to nelíbí a je potřeba používat to INSERT IGNORE.

Víš, jak se pozná dobrý/á programátor/programátorka? Nad problémem přemýšlí, klidně delší dobu než trvá psaní samotného kódu.
Prostě si nad tím sedni, klidně i vypni počítač, vezmi tužku a papír a zkus si to nakreslit jako několik tabulek, které se vzájemně využívají.
Určitě na něco přijdeš. :-)
TomášK
Profil
Rozbil (ehm...dekomponoval :-)) bych tu tabulku na dvě, tím se odstraní redundance (spíš jen přesunul pole, předpokládám, že tabulky terminy a udalosti už existují):
terminy(id, udalost_id, datum)
zkouska(id, termin_id, student_id, zacatek)

Naopak, datum a čas ve zvláštní tabulce je asi z pohledu normálních forem dobře, ale zdá se mi daleko jednodušší uložit to přímo do tabulky - rychlost i objem v databázi budou hodně podobné (datum se ukládá jako číslo, stejnětak reference) a bude se s tím daleko lépe pracovat. Pokud by datum a čas zůstaly ve stejné tabulce, tak bych z toho udělal jeden sloupec - datetime.

marcus33cz:
Ale to je základní princip identifikátoru - cílem je, aby se ten sloupec ID (v tvém případě id_termínu a id_události) NEOPAKOVAL
To platí to pro primární klíč tabulky, tedy pro sloupec id v tabulce události apod., v ukázané tabulce určitě nebude ani na id_terminu a id_udalosti auto_increment. Nebylo by ani nic špatného na tom, kdyby v tabulce bylo víckrát stejné id_terminu a id_udalosti, pokud by se jednalo o nezavisle sloupce (což zde neplatí). Ale určitě to nejde takhle generalizovat.

V databázi to takhle nemá být, což se dá poznat už z toho, že se jí to nelíbí a je potřeba používat to INSERT IGNORE.
INSERT INGORE jen nezahlásí chybu, pokud se záznam nepovede vložit. Jeho použití neznačí špatnou strukturu databáze.

Blok podporuju :-)
tiso
Profil
Tori: predpokladám že rozbitím na 2 termíny chceš vlastne skúšajúcemu zabezpečiť obedovú prestávku. V tom prípade ti tam chýba limit na počet študentov na termín. Riešil by to ten čas do, ktorý si spomenula.
Tori
Profil
Díky za reakce.

marcus33cz:
Ale to je základní princip identifikátoru - cílem je, aby se ten sloupec ID (v tvém případě id_termínu a id_události) NEOPAKOVAL
Pardon, špatně jsem se vyjádřila - "hodnoty" v té napsané tabulce, ale ID v databázi. Ta napsaná tabulka spíš znázorňovala pole, které chci uložit, než výpis databázové tabulky.
Tady je současné schéma. Vidno tedy, že jsem neukládala časy+datumy jako hodnotu, ale ID(FK) z jiné tabulky. A právě při vkládání časů/datumů jsem používala INSERT IGNORE (v kombinaci s indexy), aby se uložily jen hodnoty, které v té tabulce ještě nejsou - od toho tam taky byla.

TomášK:
zdá se mi daleko jednodušší uložit [datum a čas] přímo do tabulky [...] (datum se ukládá jako číslo...
Souhlasím, tak bych dala jen jeden několikanás.INSERT bez SELECTu. Snažila jsem se držet NF, zde zřejmě zbytečně. "Jako číslo" předpokládám znamená timestamp, že?

v ukázané tabulce určitě nebude ani na id_terminu a id_udalosti auto_increment.
Ne, každý řádek má sice své id (spíš pro forma), ale jinak to je jen vazební tabulka pro těch 5 ostatních. Jinak tabulka terminy slouží jen jako generátor unik. ID, jiný účel nemá.
Tori
Profil
tiso:
Ano. "Termínem" myslím nepřerušený blok času, kterých může být několik ve stejný den. Počet studentů/termín je vlastnost celé události (zkouška, konzultace), takže se ukládá do její tabulky.

Riešil by to ten čas do, ktorý si spomenul.
Pardon, nerozumím. Co máte na mysli?

Jinak zatím to je navržené tak, že ke každému termínu se vytvoří tolik řádků, kolik v něm bude rezervovatelných míst. Tzn. pokud se mohou napsat na stejný čas tři studenti, budou v DB 3 řádky lišící se pouze ID studenta (budou-li rezervované). Takže to, jestli se v nějakém políčku rozvrhu zobrazí link "rezervovat", není řešené jako (počet studentů/termín minus počet rezervací na tento čas), ale (pokud z DB přišlo ID prvního volného místa na tento čas, zobraz link). Při rezervaci termínu a její změně/zrušení tedy nebude INSERT/DELETE, ale jen UPDATE.
tiso
Profil
Tori: čas "do" som myslel tento: [#1] „Lektor vypíše 1+ termínů (= konkrétní den, od-do)

Tvoj návrh s prázdnymi riadkami ti možno vyhovuje, ale z hľadiska návrhu nie je úplne správny. Pokiaľ sa totiž všetci študenti nezapíšu na termín, bude obsahovať zbytočné riadky. Lepšie je zapisovať d DB až prihlásených študentov, viď návrh od TomášK.
TomášK
Profil
tiso:
V mém návrhu jsem tohle neřešil do detailů. Řešení Tori může mít své opodstatnění. Pokud jsou na zkoušce přihlášeni čtyři studenti a třetí se odhlásí, stačí ji z daného záznamu odstranit id_studenta a termín se zobrazí jako volný (s uloženým časem). Pokud budu ukládat jen přihlášené studenty, budu muset ještě ukládat jaký je časový interval mezi dvěma studenty (abych poznal, kde jsou ještě mezery), kolik studentů se může zapsat na termín (abych poznal, kdy termíny končí), u každého zkoušeného pak zřejmě lépe kolikátý je v pořadí než přesný čas zkoušení (aby se to nepokazilo, když změním mezeru mezi dvěma studenty). Je to o něco flexibilnější, ale rychlejší spíš ne (kvůli nutnosti výpočtu časů) a dotazy to spíš zesložití než zjednoduší.
Rozhodl bych se podle toho, co se stane, když se student škrtne ze zkoušky. Posunou se ostatní tak, aby zkoušející měl trvalý přísun studentů a skončil dřív nebo student přijde v čas, který si zapsal?
tiso
Profil
TomášK: a prečo to píšeš mne?
Tori
Profil
TomášK:
Posunou se ostatní tak, aby zkoušející měl trvalý přísun studentů a skončil dřív nebo student přijde v čas, který si zapsal?
Hm, to mne nenapadlo, že by seznam studentů fungoval jako zásobník. Vycházela jsem z konkrétní situace lektorky, pro kterou to dělám - tj., že tak či tak by byla v kanclu majíc ještě jiné práce nad hlavu, takže když student vypadne, zůstane volné okno.

...kolik studentů se může zapsat na termín (abych poznal, kdy termíny končí), u každého zkoušeného pak zřejmě lépe kolikátý je v pořadí než přesný čas zkoušení
Asi by byl nutný spíš ten čas, protože v požadavcích je, aby se mohlo na stejný čas napsat i více studentů (např. na kolokviální zkoušku). Moje chyba, nepřišla jsem na rozumné pojmenování jednoho "okénka v rozvrhu", takže to pletu dohromady s celým termínem.
Ale interval mezi dvěma studenty + počet studentů/okénko rozvrhu ukládám tak či tak, takže by šlo i ukládat jen přihlášené studenty, jak píše tiso.

Vezmu si (opět) ten doporučovaný blok a snad na něco přijdu. Děkuji za užitečné rady (i ostatním)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0