Diskuze: SQL dotaz pro výběr posledních zpráv
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.

Vlastník

Zobrazeno 46 zpráv z 46.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
SELECT
uzivatele_A.nick,
uzivatele_B.nick,
zprava.text,
FROM zprava
JOIN uzivatele uzivatele_A ON zprava.od=uzivatele_A.id
JOIN uzivatele uzivatele_B ON zprava.komu=uzivatele_B.id;
Takhle by to asi mělo být s tím že tabulka "uzivatele" je nazev tabulky s uctama, a pocitam s tim ze tam bude sloupec "id". A sloupec "nick" zmen za nazev sloupce ve kterym je ulozeny nick.
Dotaz jsem nezkoušel, ale podle mně by to mělo fungovat
Ono to není tak jednoduché. Potřebuji vybrat vždy jen tu poslední zprávu a ta může být buď příchozí nebo odchozí.
však tam se vypisuje i datum (čas), seřaď to podle toho.
no, kdybych viděl tu strukturu DB kompletně, tak bych ti to poskládal, ale takhle toho asi moc nevykoumám
Strukturu jsem ti napsal, nic víc tam není Jako výsledek potřebuji kolekci
posledních zpráv jednotlivým členům od určitého
člena.
A ty zprávy mohou být buď příchozí (idčko člena je v od) nebo odchozí (idčko člena je v komu), je třeba vybrat tu poslední.
ale tak na to bys potřeboval u té zprávy znát buď ID, nebo čas odeslání... a pokud tam máš jen ty 3 sloupce co píšeš, tak je to dost těžký seřadit od nejnovějších
No právě, proto sem píšu Tak alespoň vybrat vždy poslední zprávu z příchozích zpráv.
Potom bych udělal to samé pro odchozí a propojil si to na úrovni PHP. Teď
vybírám všechny, což je strašně pomalé.
dobře... okdud se bere to datum které se zobrazuje v doručených zprácách ?
Datum je samozřejmě součástí zprávy. Promiň, na to jsem zapomněl.
moment, součástí zprávy,takže má vlastní sloupec předpokládám ?
SELECT
uzivatele_A.nick,
uzivatele_B.nick,
zprava.text,
FROM zprava
JOIN uzivatele uzivatele_A ON zprava.od=uzivatele_A.id
JOIN uzivatele uzivatele_B ON zprava.komu=uzivatele_B.id;
WHERE uzivatele.od=/dosazeni promenne z PHP/
ORDER BY datum DESC
LIMIT 10
Píšu si třeba s deseti lidmi a potřebuji, aby mi dotaz ideálně vrátil
10 výsledků, kde budou vidět poslední zprávy které jsem těm lidem poslal
nebo které od nich přišly. Každé řešení je lepší než současné
Tohle vybere všechny zprávy ale, můžou jich být tisíce. Potřeboval bych jen těch pár posledních.
upravil jsem to
stačí: LIMIT 10
Nemyslím si, že to bude fungovat. Tohle vybere 10 posledních zpráv (klidně všechny od jednoho člověka). Já potřebuji vybrat posledních několik lidí, se kterými jsem si psal.
jo, už tomu asi začínám pomalu rozumět
v tom případě snad takhle:
SELECT
uzivatele_A.nick,
uzivatele_B.nick,
zprava.text,
FROM zprava
JOIN uzivatele uzivatele_A ON zprava.od=uzivatele_A.id
JOIN uzivatele uzivatele_B ON zprava.komu=uzivatele_B.id;
WHERE uzivatele.komu=/dosazeni id "komu" z PHP/
ORDER BY datum DESC
LIMIT 10
To je pořád stejné, jen to vybere posledních 10 příchozích zpráv,
opět klidně všechny od jednoho člověka. Zkusím se nad tím ještě zítra
nějak zamyslet Kit
by nevěděl?
no, asi pořád nějak špatně chápu o co přesně ti jde, jinak MySQL pro mně není problém (alespoň si to myslím) , ale zítra si to pročtu znova a snad to už pochopím správně
Ááááá už asi vím....
GROUP BY zprava.od
ty tu tabulku máš bez sloupce ID? Jak pak mažeš určitou zprávu?
Ten výběr by byl s tím sloupcem ID také jednodušší, stačilo by vybrat
posledních X ID s podmínkou, že OD a KOMU by byl uživatel.
Věděl, už jsem něco podobného řešil. Podívám se na to zítra u PC.
Grouping mě také napadlo, ale nevím jak zadat že chci v každé skupině jen tu nejposlednější zprávu. Já sem za chvíli hodím nějaký obrázek, aby to bylo lépe představitelné.
Jo, to mě taky napadlo. Vybrat si distinctem IDčka lidí se kterými jsem si psal a potom vybrat ke každému IDčku nejposlednější zprávu. To druhé ale nevím jak udělat, když tam dám:
select *
from zprava
where od in (select distinct...) or komu in (select distinct...)
order by datum desc
limit 1
Tak mi to vybere jeden výsledek pokud se nepletu.
On je to docela problém, protože porušuješ 2NF. Dotaz bude o to složitější. Nejprve si to vyzkouším a pak to sem pošlu.
Můžeme to zjednodušit na ten distinct. Dejme tomu, že si uložím výsledek tohoto dotazu:
select distinct komu
from zprava
where komu = id_clena
Od toho by se asi dalo odpíchnout, mám idčka těch, se kterými jsme si psal. Jak mohu následně vybrat kolekci nejnovějších příspěvků s lidmi s tímto ID? Asi tam bude figurovat nějaký poddotaz, ale nenapadá mě jak to udělat.
Nebo tam mohu přidat tabulku konverzace a denormalizovat to, ale tomu bych se chtěl vyhnout, protože bych se musel při odeslání každé zprávy zase ptát countem jestli existuje konverzace (mohu psát někomu, s kým jsem si ještě nepsal). Proto to zde není udělané jako na fóru, kde je to jednoduše denormalizování přes tabulku vlakno.
Spíš normalizovat. V jedné tabulce mít zprávy s id a timestampem, ve druhé seznam odesílatelů a příjemců s cizím klíčem na zprávy. Výhodou bude, že příjemce si nežádoucí zprávu bude moct smazat nezávisle na odesílateli.
Bohužel MySQL neumí cizí klíče, takže mazání textu zpráv je o něco složitější.
Nějak v tom nevidím tu výhodu, problém mi přijde úplně stejný, jen musím ještě joinovat.
Ono to řeší spíš navazující problémy. Však počkej chvilku, než se k tomu PC dostanu.
Dobře, díky Jsme na to
zvědavý, protože já opravdu netuším. Uměl bych to udělat jedině tak,
že bych v cyklu volal selecty na poslední zprávu, což není asi
ideální.
Tak to není ideální ani náhodou. Zejména pokud takový report potřebuješ vypsat každou chvilku. Jeden trochu složitější select musí stačit.
Zkus se mezitím podívat na
http://www.linuxsoft.cz/article.php?…
Dnes mi to nějak nemyslí, sesmolil jsem tohle:
SELECT * FROM (
SELECT * FROM (
SELECT cas, komu AS partner, zprava FROM chat WHERE od=:od
UNION ALL
SELECT cas, od AS partner, zprava FROM chat WHERE komu=:komu
) AS schat ORDER BY cas DESC
) AS sschat
GROUP BY partner ORDER BY cas DESC LIMIT 10;
ale netuším, jak moc to bude rychlé. Ani jsem netestoval, zda je to funkční.
Dobře, dnes jsem zahlcený články, zítra se do toho pustím
Nějak se tomu nechce: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from=:from UNION ALL". Nelíbí se tomu ta dvojtečka. Poslal jsem ti to celé do PM, nechci to tu vystavovat.
Ta dvojtečka funguje jen v prepared statements. Nahrazuje ošklivě
znějící funkci mysql_real_escape_string()
a zpřehledňuje
zápis SQL dotazu. Starý ovladač MySQL s tím pracovat neumí, ale jede to v
MySQLi a PDO.
Běžně místo d
používám otazník, který však funguje pozičně.
Jelikož devbook zatím jede na té pitomé dibi, tak to zatím použít nemohu :-/ Je nějaký způsob, jak bych to mohl teď zprovoznit? Pokusím se té dibi co nejdříve zbavit, neskutečně mě omezuje ve všech ohledech.
Napsal jsem ti to přece v PM.
Tohle je jeden z důvodů, proč se mi nelíbí ORM frameworky. Buď jsou primitivní a skoro nic neumí, anebo jsou to molochy, které i jednoduché úkoly řeší stylem "kanón na vrabce". Než abych přemýšlel, co to udělá s SQL, raději si to SQL napíšu sám.
Něco se dá řešit i přes pohledy. Dibi s takovým pohledem bude zacházet jako s běžnou tabulkou.
V tom řešení jsem vlastně ani nepopsal vazbu na tabulku nicků. Byl to jen takový hrubý nástřel, abys měl nad čím přemýšlet. MySQL má v dotazech poddobného typu poměrně omezené možnosti a není úplně jednoduchá najít správné a přitom i efektivní řešení. Třeba na něco elegantního během dne přijdu, ale v tuto chvíli bych jen doladil dotaz, který jsem už poslal.
Místo :from
a :to
se dosadí ID uživatele, přo
kterého hledáš ty poslední zprávy.
Nojo, mě to nedošlo, používám vždycky otazník a zapomněl jsem, že to
jde i takhle. Ten dotaz funguje, zdá se být i dostatečně rychlý
Nad vazbou na uživatele přemýšlím, předpokládám, že na to bude nějaký korelovaný poddotaz, ale nedaří se mi na to přijít.
Zobrazeno 46 zpráv z 46.