NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
IT rekvalifikace s podporou uplatnění. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Avatar
Martin Konečný (pavelco1998):22.12.2012 11:14

Ahoj.

Potřebuji navrhnout jednu nebo více tabulek pro odesílání zpráv dvěma způsoby:

  1. uživatel-uživatel
  2. uživatel-skupina

S tím, že uživatel uvidí příchozí, odeslané a skupinové zprávy.
Také bude mít každý uživatel možnost si zprávu smazat.
Když vytvořím jednu tabulku, vypadala by asi takto:

[message] (
id INT
author_id INT
recipient_id INT
subject VARCHAR()
content TEXT -- textový obsah zprávy
time DATETIME
report INT -- 1 = uživateli přijde oznámení, že má novou zprávu (stačí jen jiná barva odkazu)
type INT -- 1 příchozí, 2 odeslané, 3 skupinové
)

V takovém případě se 'subject' a 'content' uloží třeba 30x (když pošlu skupinovou zprávu 30ti lidem), což mi přijde poměrně zbytečné.

Nezná někdo lepší řešení?
Děkuji.

Odpovědět
22.12.2012 11:14
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:22.12.2012 11:47

Zkus to rozdělit na dvě tabulky:

CREATE TABLE message (
   id int,
   subject text,
   content text,
   time datetime,
   type int);

CREATE TABLE cover (
   id int,
   mesage_id int,
   uzivatel_id int,
   type int);

Zpráva bude pouze 1× v tabulce message, vytvoří se k ní záznamy odesílateli i příjemci (resp. příjemcům) do tabulky cover.

S tím reportem bych byl opatrnější, ten se dá uložit přímo do tabulky příjemce ve formě počitadla.

Nahoru Odpovědět
22.12.2012 11:47
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):22.12.2012 20:35

Děkuji za návrh. Mohl bys mi, prosím tě, upřesnit, co přesně bude message.type a cover.type?

Nahoru Odpovědět
22.12.2012 20:35
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:22.12.2012 20:48

message.type nebude

cover.type INT -- 1 příchozí, 2 odeslané, 3 skupinové

Odesílatel bude mít type 2, příjemce 1 nebo 3. Ke každému záznamu v message budou 2 záznamy v cover. Když příjemce "smaže zprávu", smaže se jeho záznam v cover. Když odesílatel "smaže odeslanou zprávu", opět se smaže jen jeho záznam v cover. Občas se smažou položky v message, na které není žádný odkaz v cover.

Nahoru Odpovědět
22.12.2012 20:48
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Martin Konečný (pavelco1998):22.12.2012 20:52

Jasně, děkuji za vysvětlení!

Editováno 22.12.2012 20:52
Nahoru Odpovědět
22.12.2012 20:52
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:22.12.2012 21:19

Ještě malá ukázka, jak se budou vypisovat přijaté, odeslané a skupinové zprávy:

SELECT subject, content FROM message WHERE id IN (
    SELECT message_id FROM cover WHERE uzivatel_id = $myid AND type = 1
)

Jenom se to bude lišit podmínkou type. Samozřejmě se to dá vylepšit o některé údaje (např. kdo a komu v message), ale to snad zvládneš. Tyto údaje tam vlastně budou 2×. Jednou pro doručování (v cover) a podruhé pro evidenci (v message). V cover se to dá udělat i triggerem, který zároveň u příjemce zvýší počitadlo nepřečtených mailů. Jedinou tvou starostí při odesílání zprávy pak bude zapsat záznam do tabulky message.

Nahoru Odpovědět
22.12.2012 21:19
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):23.12.2012 10:35

Co se týká toho počítadla nepřečtených zpráv, pochopil jsem správně, že daný počet bude v nové tabulce?

Nahoru Odpovědět
23.12.2012 10:35
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:23.12.2012 11:26

Nemusí být nová. To počitadlo může být sloupeček v tabulce uživatelů/hráčů.

Nahoru Odpovědět
23.12.2012 11:26
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):23.12.2012 15:40

Děkuji za nápad s triggery. Sice jsem s nimi dělal prakticky poprvé, ale nakonec to funguje a funguje to skvěle.

Nahoru Odpovědět
23.12.2012 15:40
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:23.12.2012 15:54

Není zač. Triggery by se měly používat všude tam, kde se dělala denormalizace databáze.

Nahoru Odpovědět
23.12.2012 15:54
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:24.12.2012 13:44

Ještě taková drobnost. Občas se řeší, že před uložením záznamu je nutné některý údaj vyhledat v jiné tabulce a záznam přidat pouze v případě, že je v té tabulce nalezen. Řešení v SQL je celkem jednoduché:

INSERT INTO message (author_id, recipient_id, subject)
    SELECT :myid, recipient_id, :subject FROM users
        WHERE name LIKE :recipient LIMIT 1;

-- :myid => id odesílatele
-- :subject => předmět zprávy
-- :recipient => jméno příjemce, které se má nahradit jeho id

A teď otázka: Dá se tato trivialita řešit v Dibi a podobných frameworcích nebo se to musí dělat více SQL dotazy? Jak by to asi vypadalo?

Nahoru Odpovědět
24.12.2012 13:44
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Kit
Kit:24.12.2012 14:01

Tak nic, už jsem to našel. SQL mi připadá přehlednější.

Nahoru Odpovědět
24.12.2012 14:01
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):24.12.2012 16:54

Dobrý nápad, nicméně mám stále v těchto dvou tabulkách problém, jak vložit ta data závisle na tom, zda existuje daný uživatel.
Prvně musím vložit do tabulky message a poté do tabulky cover (jejíž sloupec message_id se bude rovnat message.id). Jenže to první vložení musí proběhnout jen tehdy, že ten uživatel existuje, což je trochu zamotané.

Nahoru Odpovědět
24.12.2012 16:54
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:24.12.2012 17:03

To první vložení do message bude viz výše. Ověřuje se tam proti tabulce users. Pokud adresát neexistuje, zpráva se nevloží, protože výsledek selectu bude prázdný. V případě úspěchu nastoupí trigger navázaný na message a vloží dva patřičné záznamy do cover.

Nahoru Odpovědět
24.12.2012 17:03
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:24.12.2012 17:26

A aby toho nebylo málo, na cover bude navázán další trigger, který v případě přidání záznamu typu přijatá nebo skupinová pošta inkrementuje příjemci čítač došlé pošty v users.

Nahoru Odpovědět
24.12.2012 17:26
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):24.12.2012 17:40

Hmm, stále mě nenapadá způsob, jak to aplikovat, když v tabulce messsage jsou sloupce id, subject, content a time. Pokud použiji ten SELECT, hlásí mi databáze chybu, že se snažím vybrat více hodnot, než kolik mohu vložit.
Možná je to triviální řešení, ale za boha nemohu přijít, jak to udělat.

Nahoru Odpovědět
24.12.2012 17:40
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):24.12.2012 17:41

Ten trigger na čítač mám již hotový a funguje (když jsem to zkoušel vložit manuálně v Admineru). Jen mám teď problém s vložením té zprávy od uživatele.

Nahoru Odpovědět
24.12.2012 17:41
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:24.12.2012 17:46

Za INSERT INTO máš v závorce 3 parametry. Za tím SELECTem musí být výběr 3 sloupců z druhé databáze. Některé můžeš nahradit konstantou nebo subselectem, ale počet musí souhlasit.

Místo čísla 3 si dosaď jakékoli jiné číslo.

Asi tam přece jen budeš muset přidat i sloupce author_id a recipient_id, aby se ten trigger měl čeho chytit.

Nahoru Odpovědět
24.12.2012 17:46
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):24.12.2012 17:55

Tak jo, děkuji za pomoc. Jestli by nebylo nakonec nejlepší vše udělat prostě do jedné tabulky s tím, že se ten předmět a obsah bude opakovat.

Nahoru Odpovědět
24.12.2012 17:55
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Kit
Tvůrce
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:24.12.2012 18:04

Uvědom si, že jsme tady řešili víc problémů, než jen duplicitu jednoho záznamu. Jeden INSERT je vždy rychlejší než dva a máš garantovánu konzistenci. Kromě toho se normalizace hodí vždy.

Nahoru Odpovědět
24.12.2012 18:04
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
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 20 zpráv z 20.