Autor Zpráva
xaverista
Profil
Zdravím,

Chtěl bych se vás zeptat na názor, radu.

Chtěl bych udělat tzv. Denní kvíz pro uživatele. Kvíz spočívá v tom, že každý den se zobrazí jedna otázka, po půlnoci další atd. Prostě bude jedna otázka přidělena jednomu dnu... Jak bych měl navrhnout databazi? Jakou možnost by jste volili vy?

1) Databáze 'otazky' sloupce (id,otazka,datum) a vybírat otázku vždy podle datumu? Toto mi přijde logičtější než za 2). Ale jelikož to chci přidávat ty otázky z webu/administrace potřeboval bych, aby se mi automaticky generoval datum, tedy aby se mi u každé nové otázky přidal datum jako kdyby auto_increment jestli by to nějak šlo i ve formátu DD.MM.YYYY

2) Databáze 'otázky' sloupce (id,otazka,pouzita), sloupec použita bude mít hodnoty 0 a 1. A každý den budu nastavovat otázce která byla použita hodnotu 1 a poté zobrazím tu, která má hodnotu 0

A ještě, jak bych mohl nejlépe vyhodnotit uživatele, kdo je na 1. 2. 3. atd. Místě?

Díky za názory. Xave
juriad
Profil
xaverista:
Co hybrid. Otázka bude mít datum nevyplněné, dokud se nepoužije nějaký den.
NULL -> zatím nebyla použita
2015-07-25 -> byla použita dnes

SELECT * FROM
((SELECT *, 1 as pref FROM otazky
WHERE datum = CURDATE())
UNION ALL
(SELECT *, 2 as pref FROM otazky
WHERE datum IS NULL)) x
ORDER BY pref
LIMIT 1

A pokud má vybraná otázka datum NULLový, updatneš ho na aktuální.

Alphard:
Máš rozhodně hezčí řešení; chtěl jsem nebo, ale padl mi tam UNION.
Alphard
Profil
Totéž by šlo bez union, jen pomocí or, ne?
select * from otazky where datum = curdate() or datum is null order by datum desc limit 1
Při tomto order by budou nenulové záznamy vždy jako první, není třeba to rešit jako sloupec.
xaverista
Profil
Ono by možná lepší bylo, jak bych mohl automaticky vytvářet datum, něco jako auto_increment? Každopádně díky za návrhy :-)
Alphard
Profil
[#4] xaverista
Taky to jde, když pominu drobné problémy s atomicitou (která v tomto případě asi nebude kritická), vyřešil by to jednoduchý trigger. Při insertu se vezme nejvyšší dostupné id a přičte se jeden den.

Ale je to tak lepší? Jak se to vezme. Když vám na stránky v jeden den nikdo nepřijde, tak má anketa skončit v propadlišti dějin? Kdyby byl použit autoincrement pro data, tak ano. Navrhované řešení představuje určitou frontu, každý den, je-li to potřeba, se vybere jedna volná otázka. Podle mě to přesně odpovídá požadavkům.


Doplňuji, že totéž, tj. přičtení k datu jeden den, jde provést na straně PHP již při vytváření otázky, viz http://stackoverflow.com/a/15564182.
xaverista
Profil
Díky moc všem :-)
xaverista
Profil
Chtěl bych se ještě zeptat, jak nejlépe vyhodnotit kvíz... Kdo skončil na 1. 2. Atd. Místě?
Podle počtu správných odpovědí, aby se mi vypsali jména.

Díky xave
juriad
Profil
xaverista:
Musíš si do databáze ukládat odpovědi uživatelů. Pak je porovnáš se správnými odpověďmi a seskupíš podle uživatele.
Asi budeš mít o hodně víc tabulek než teď předpokládáš:

kvízy (id, datum) # kvíz je sada otázek pro nějaký den
otázky (id, otázka, kvíz_id) # kvíz obsahuje otázky
odpovědi (id, otázka_id, odpověď, správně) # otázky mají odpovědi; některé z nich jsou správné)
uživatelé (id, jméno, ...) # uživatelé se přihlašují
uživatelé_kvízy (id, kvíz_id, uživatel_id, body, pořadí) # jaké kvízy uživatel vyplnil a kolik z nich má bodů a kolikátý skončil (tyto statistické informace jsou dopočítány po následující půlnoci, kdy už je kvíz uzavřený)
uživatelé_odpovědi (uživatelé_kvízy_id, otázka_id, odpověď_id) # jak v kterém kvízu, který uživatel vyplnil odpověděl na otázku

Tento systém je dostatečně robustní, aby umožnil otázky s právě jednou odpovědí, otázky s alespoň jednou odpovědí i otázky s libovolným počtem odpovědí.
Databázový dotaz na zobrazení kvízů je snad jasný. Databázový dotaz na zpracování bude možná brutální, ale stále napsatelný. Základní idea spočívá v Některé časteji řešené dotazy pro MySQL - FAQ » Nalezení položek mající všechny hledané vlastnosti. Tím vypočítáš body a následně pomocí Některé časteji řešené dotazy pro MySQL - FAQ » "Setřepání" sloupce spočítáš pořadí uživatelů.
Alphard
Profil
Snad se juriad nebude zlobit :-), ale viděl bych to možná trošičku jinak.

uživatelé_kvízy (id, kvíz_id, uživatel_id, body, pořadí)
Bez sloupce pořadí bych se snad i obešel. Stačí mi body, pořadí se vyřeší při výpisu.

tyto statistické informace jsou dopočítány po následující půlnoci, kdy už je kvíz uzavřený
Tento bod bych právě obešel, protože body mohu spočítat hned při hlasování.

Celkové řešení by bylo univerzálnější, mohl bych zobrazovat třeba nejlepší uživatele za poslední měsíc tím stejným scriptem.
juriad
Profil
Alphard:
Ten sloupec je tam k tomu, aby se pro každý kvíz uživatele nemuselo dopočítávat, kolikátý uživatel skončil (JOIN uživatelé_kvízy uk2 ON uk1.kvíz_id = uk2.kvíz_id AND uk2.body < uk1.body GROUP BY uk1.id).

Máš pravdu, body je možné vypočítat hned po odeslání; pořadí nikoli. Je tedy otázkou, jak moc bude jeho výpočet náročný. Asi bych jej skutečně zahodil; později jej lze kdykoli přidat a sloužil by jen pro cachování hodnoty u uzavřených kvízů.

Pořadí je navíc jen jeden z údajů. Lze sledovat ve statistikách věrnost uživatelů (jak často vyplňují), procentní úspěšnost v jednotlivých měsících a další. To je další důvod, proč se k němu nechovat speciálně.

Nezlobím se; jsem naopak rád, že mě nutíš se nad tím zamyslet :-)

xaverista:
Doufám, že tě má odpověď, která obhajuje všechny možnosti, příliš nezmate.
xaverista
Profil
Díky, chtěl bych to každopádně uodatovat po půlnoci, aby se nedozvěděl hned jestli odpověděl správně či špatně, aby info nepredal dále...

Mno... Není nějaká možnost že bych hned ukládal zda byla odpověď správná či špatná a poté jen nějaký COUNT a výběr od nejvyšších počtu správných odpovědí?

Každopádně moc děkuji za pomoc xave
Alphard
Profil
xaverista:
Není nějaká možnost že bych hned ukládal zda byla odpověď správná či špatná a poté jen nějaký COUNT a výběr od nejvyšších počtu správných odpovědí?
To je přesně ta verze, kterou jsem navrhoval já. Ihned po hlasování se vyhodnotí správnost a přidělí se body.
Pořadí (pro jednoho uživatele a jeden kvíz) se zjistí pomocí count, přesně jak píšete. Spočítá se počet uživatelů, které mají více bodů, a přičte se 1. Ten join, který popisoval juriad, dokáže spočítat výsledky pro více kvízů najednou.

Časové omezení, které hledáte, je zcela triviální. Na nějaké stránce s výsledky hlasování zobrazíte pouze starší ankety, což je jedna podmínka v SQL; where datum < curdate().

[#10] juriad
Naprosto souhlasím. Uvažoval jsem stejně, jen jsem došel k závěru, že alespoň zatím není třeba aplikaci komplikovat tím cachováním.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

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