Autor | Zpráva | ||
---|---|---|---|
tečky Profil * |
#1 · Zasláno: 6. 11. 2013, 23:07:06
Dobrý den, omlouvám se za ten patrně zavádějící nadpis...dlouho jsem si lámal hlavu jak téma pojmenovat a nepřišel jsem na nic výstižného. Jde o to, že mám dvě tabulky které organizují vzkazy a teď potřebuju vypsat s kým daný uživatel již komunikoval, ale ve výpisu těch nicků nechci, aby byl uváděn i nick toho uživatele, který o to zažádal. Jen nicky se kterýma komunikoval a né jeho vlastní nick. A to se mi nedaří. Mám toto :
SELECT id_uzivatele, nick_uzivatele FROM vzkazy_data JOIN uzivatele ON (id_odesilatel_vzkazy_data = id_uzivatele) OR (id_adresat_vzkazy_data = id_uzivatele) WHERE (id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele'].") OR (id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele'].") GROUP BY id_uzivatele, nick_uzivatele ale právě že to vypisuje i uživatele ke kterému nálaží to $_SESSION['id_uzivatele'] ... čili jeho nick. To nechci. Zkoušel jsem různé kombinace OR a AND, ale nepodařilo se mi to vyřešit. Děkuji. |
||
joe Profil |
#2 · Zasláno: 6. 11. 2013, 23:13:19
Jestli jsem to správně pochopil, takto by to snad mělo fungovat.
SELECT id_uzivatele, nick_uzivatele FROM vzkazy_data JOIN uzivatele ON (id_odesilatel_vzkazy_data = id_uzivatele) OR (id_adresat_vzkazy_data = id_uzivatele) WHERE id_uzivatele != ".$_SESSION['id_uzivatele']." AND ((id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele'].") OR (id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele'].")) GROUP BY id_uzivatele, nick_uzivatele |
||
Tori Profil |
#3 · Zasláno: 6. 11. 2013, 23:20:50
A tohle jste zkoušel?
SELECT id_uzivatele, nick_uzivatele FROM vzkazy_data JOIN uzivatele ON (id_odesilatel_vzkazy_data = id_uzivatele) OR (id_adresat_vzkazy_data = id_uzivatele) WHERE (id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele'].") OR (id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele'].") GROUP BY id_uzivatele, nick_uzivatele HAVING id_uzivatele != ".$_SESSION['id_uzivatele'] |
||
tečky Profil * |
#4 · Zasláno: 7. 11. 2013, 13:39:08
Pánové moc vám děkuji. Fungují obě řešení. :))) To HAVING jsem vůbec ani neznal... teď jenom které je lepší (rychlejší)?
|
||
Tori Profil |
#5 · Zasláno: 7. 11. 2013, 14:08:45
Neni zač, nejsem pán. :)
Rychlost si můžete porovnat sám a jednodušeji, než kdybychom si my museli nejdřív vytvořit nějaká testovací data. Rozdíl je v tom, že podmínka v [#2] omezí data, která se vyberou z tabulek (tj. ještě před seskupením), kdežto [#3] nejřív vybere všechny uživatele, seskupí podle ID, a pak vyhodí ten jeden řádek. Takže asi [#2] by mělo být rychlejší. Navrhla jsem to jen proto, že se to tak samo nabízelo, přidat za GROUP BY podmínku na vyhození jednoho nechtěného řádku. |
||
tečky Profil * |
#6 · Zasláno: 7. 11. 2013, 14:55:06
Tori:
Mé omluvy dámo. A ještě jednou dík. :))) |
||
Kajman Profil |
#7 · Zasláno: 7. 11. 2013, 14:59:21
tečky:
Pro zajímavost zkuste do měření rychlosti zahrnout i variantu SELECT u.id_uzivatele, u.nick_uzivatele FROM ((SELECT DISTINCT id_adresat_vzkazy_data id_uzivatele FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = $id_uzivatele) UNION (SELECT DISTINCT id_odesilatel_vzkazy_data id_uzivatele FROM vzkazy_data WHERE id_adresat_vzkazy_data = $id_uzivatele)) v JOIN uzivatele u ON v.id_uzivatele = u.id_uzivatele |
||
Časová prodleva: 4 dny
|
|||
tečky Profil * |
#8 · Zasláno: 11. 11. 2013, 18:13:52
Prosim Vás já s tím mám ještě jeden problém... ještě potřebuju ty výsledky mít sežazený tak aby nahoře byli nejnovější komunikace a dole nejstarší... k tomu účelu jsem zkusil využít tady ten vnořenej select od Kajman, ale představoval jsem si to asi moc jednoduše...
SELECT u.id_uzivatele, u.nick_uzivatele FROM ((SELECT DISTINCT id_adresat_vzkazy_data id_uzivatele FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = 2 ORDER BY cas_zpravy) UNION (SELECT DISTINCT id_odesilatel_vzkazy_data id_uzivatele FROM vzkazy_data WHERE id_adresat_vzkazy_data = 2 ORDER BY cas_zpravy)) v JOIN uzivatele u ON v.id_uzivatele = u.id_uzivatele; :/ |
||
Tori Profil |
Zkuste tohle (doufám, že sloupec cas_zpravy má správný datový typ pro ukládání času):
SELECT u.id_uzivatele, u.nick_uzivatele FROM ((SELECT id_adresat_vzkazy_data id_uzivatele, MAX(cas_zpravy) cas FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = 2 GROUP BY id_adresat_vzkazy_data ORDER BY NULL) UNION (SELECT id_odesilatel_vzkazy_data id_uzivatele, MAX(cas_zpravy) cas FROM vzkazy_data WHERE id_adresat_vzkazy_data = 2 GROUP BY id_odesilatel_vzkazy_data ORDER BY NULL) ORDER BY cas DESC) v JOIN uzivatele u ON v.id_uzivatele = u.id_uzivatele; |
||
tečky Profil * |
#10 · Zasláno: 11. 11. 2013, 20:44:50
jj je to datový typ TIMESTAMP... ale toto mi nefunguje.. vyhazuje to
ERROR: syntax error at or near "GROUP" ŘÁDKA 12: GROUP BY id_odesilatel_vzkazy_data ^ |
||
Tori Profil |
#11 · Zasláno: 11. 11. 2013, 20:59:02
Zapomněla jsem vyhodit to ORDER BY cas_zpravy, opraveno.
|
||
tečky Profil * |
#12 · Zasláno: 11. 11. 2013, 21:08:26
no tak teď
ERROR: non-integer constant in ORDER BY ŘÁDKA 7: ORDER BY NULL) |
||
Tori Profil |
#13 · Zasláno: 12. 11. 2013, 07:21:09
Tak tuhle chybu vidím poprvé, a to už jsem GROUP BY + ORDER BY NULL použila hodněkrát. Nevím, co se databázi nelíbí. Zkuste oba výskyty ORDER BY NULL vyhodit. (Totiž při použití GROUP BY se automaticky řadí podle sloupce/-ů, které se seskupují, což je tady zbytečné a chtěla jsem teda databázi ušetřit trochu práce.)
Přitom i v manuálu radí to samé: „If you use GROUP BY, output rows are sorted according to the GROUP BY columns as if you had an ORDER BY for the same columns. To avoid the overhead of sorting that GROUP BY produces, add ORDER BY NULL .“ - Kdyby mi někdo ochotný vysvětlil, proč to v tomto případě nelze použít, budu moc ráda.
|
||
Kajman Profil |
Na tom celém se musí udělat také group by. Čas poslední odeslané a přijaté zprávy od jednotlivých uživatelů bude různý, tak ty řádky nevyhodí union jak v první variantě.
SELECT v.id_uzivatele, u.nick_uzivatele, Max(v.cas) posledni FROM ((SELECT id_adresat_vzkazy_data id_uzivatele, Max(cas_zpravy) cas FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = 2 GROUP BY id_adresat_vzkazy_data) UNION ALL (SELECT id_odesilatel_vzkazy_data id_uzivatele, Max(cas_zpravy) cas FROM vzkazy_data WHERE id_adresat_vzkazy_data = 2 GROUP BY id_odesilatel_vzkazy_data)) v JOIN uzivatele u ON v.id_uzivatele = u.id_uzivatele GROUP BY v.id_uzivatele, u.nick_uzivatele ORDER BY posledni DESC |
||
Tori Profil |
#15 · Zasláno: 12. 11. 2013, 09:19:00
Kajman:
Mohla bych ještě poprosit o vysvětlení, proč tam to ORDER BY NULL vyhazovalo chybu? |
||
Kajman Profil |
#16 · Zasláno: 12. 11. 2013, 09:28:24
Tori:
Tak to netuším. Třeba to dělá jen verze nebo konfigurace, co má tečky. |
||
tečky Profil * |
#17 · Zasláno: 12. 11. 2013, 16:06:02 · Upravil/a: tečky
A nějak jinak jak bych to mohl udělat?? Tohle už je na mě moc složitý docela... ještě jsem nedělal nikdy takhle velkej dotaz. :/ sem lama
ten dotaz dělám v postgres... jestli to neni tim. |
||
Kajman Profil |
#18 · Zasláno: 13. 11. 2013, 08:52:14
tečky:
„Tohle už je na mě moc složitý docela... ještě jsem nedělal nikdy takhle velkej dotaz.“ Mělo by stačit nahradit ty dva výskyty čísla 2 za skutečné id uživatele. Na tom není nic složitého. Pokud se do toho chcete ponořit, tak začněte studovat postupně jednotlivé vnitřní závorky. „ten dotaz dělám v postgres... jestli to neni tim.“ Ano, ta chyba s order by null pro optimalizaci pro mysql tím bude. Ale dotaz z [#14] by měl jít i v postresql. |
||
tečky Profil * |
#19 · Zasláno: 14. 11. 2013, 13:59:35
Kajman:
Děkuju Vám za trpelivost. Teď dotaz už funguje. :) |
||
Časová prodleva: 9 dní
|
|||
tečky Profil * |
#20 · Zasláno: 23. 11. 2013, 18:18:14
Jenom poslední ještě drobnost... potřebuju tomu udělat limit a stránkování... takže jsem to udělal prostě takto a přijde mi to správně...
SELECT v.id_uzivatele,u.nick_uzivatele, Max (v.cas) posledni FROM (( SELECT id_adresat_vzkazy_data id_uzivatele, Max (cas_zpravy_vzkazy_data) cas FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_adresat_vzkazy_data limit 20 offset ".cislo_stranky." ) UNION ALL ( SELECT id_odesilatel_vzkazy_data id_uzivatele, Max (cas_zpravy_vzkazy_data) cas FROM vzkazy_data WHERE id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_odesilatel_vzkazy_data limit 20 offset ".cislo_stranky." ) ) v JOIN uzivatele u ON v.id_uzivatele = u.id_uzivatele GROUP BY v.id_uzivatele,u.nick_uzivatele ORDER BY posledni DESC limit 3 Je moje logika správná? Jako jestli je to elegantní a jestli to bude za každých okolností bude fungovat správně, nebo jestli bych to neměl dělat jinak... ? přijde mi logické dát ty limity napřed ke každému vnořenému selektu, protože stejně ve výsledku, těch výsledků nebude víc jak 20 a pak dám limit tomu selektu nadřazenému. funguje mi to.. testoval jsem to s nějakýma datama, ale zajímá mě jestli nemůže nastat případ, kdy to nebude fungovat správně s ohledem na to stránkování. podle mě se děje to že ... se provedou vnořené selekty a tam se to seřadí podle času ... pak se to spojí dohromady a znova se to s limitem seřadí podle času, takže by to teoreticky podle mě mělo za všech okolností fungovat správně. |
||
Tori Profil |
tečky:
„podle mě se děje to že ... se provedou vnořené selekty a tam se to seřadí podle času“ - tohle se neděje, u vnitřních selectů chybí ORDER BY, takže se řadí jen implicitně podle sloupce v GROUP BY. |
||
tečky Profil * |
#22 · Zasláno: 23. 11. 2013, 19:58:08 · Upravil/a: tečky
aha ... no to groub by tam do toho vložit nějak nějde takže prostě takhle
SELECT v.id_uzivatele,u.nick_uzivatele, Max (v.cas) posledni FROM (( SELECT id_adresat_vzkazy_data id_uzivatele, Max (cas_zpravy_vzkazy_data) cas FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_adresat_vzkazy_data ) UNION ALL ( SELECT id_odesilatel_vzkazy_data id_uzivatele, Max (cas_zpravy_vzkazy_data) cas FROM vzkazy_data WHERE id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_odesilatel_vzkazy_data ) ) v JOIN uzivatele u ON v.id_uzivatele = u.id_uzivatele GROUP BY v.id_uzivatele,u.nick_uzivatele ORDER BY posledni DESC limit 20 offset ".cislo_stranky." *orava ORDER BY se tam nedá nějak vložit |
||
Kajman Profil |
#23 · Zasláno: 23. 11. 2013, 22:01:45
Ve vnitřních dotazech může být
order by cas desc limit dvacetinásobekcislastrankyplusdvacet |
||
Časová prodleva: 3 dny
|
|||
tečky Profil * |
#24 · Zasláno: 26. 11. 2013, 17:11:34
Prosimvás ještě jedna poslední věc a už s tim dám pokoj. Já se to teď ještě marně snažim spočítat... buď to je to syntax error nebo to počítá špatně... tak jak je to tady [#22] bez toho limitu to hodí správnej výsledek... ale já ho použít nemůžu použít právě proto že je tam ten limit už, takže to musim dalšim dotazem přepočítat znovu. (?) když to ělám takhle tak to počá špatně.
SELECT count(*) FROM (( SELECT count(*) FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = 9 GROUP BY id_adresat_vzkazy_data ) UNION ALL ( SELECT count(*) FROM vzkazy_data WHERE id_adresat_vzkazy_data = 9 GROUP BY id_odesilatel_vzkazy_data ) ) as foo GROUP BY foo; Děkuji za shovívavost. |
||
Kajman Profil |
#25 · Zasláno: 26. 11. 2013, 19:38:59
SELECT count(*) radku FROM ((SELECT DISTINCT id_adresat_vzkazy_data id_uzivatele FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = $id_uzivatele) UNION (SELECT DISTINCT id_odesilatel_vzkazy_data id_uzivatele FROM vzkazy_data WHERE id_adresat_vzkazy_data = $id_uzivatele)) v |
||
tečky Profil * |
#26 · Zasláno: 26. 11. 2013, 21:38:04
Kajman:
děkuji |
||
Časová prodleva: 3 měsíce
|
|||
tečky Profil * |
#27 · Zasláno: 14. 2. 2014, 21:59:27
omlouvám se, ale ještě jednou musim načít toto téma, [#22] protože jsem zjistil, že tam ještě potřebuju id té zprávy, takže jsem tam přidal to ID takto :
MAX (id_vzkazu_data) as id a chci se zeptat jestli takhle se to má dělat?? tu agregační funkci MAX tam musim dát, protože Postgres vyžaduje při použití GROUP BY provázanost s nějakou agregační funkcí... aspoň tak jsem to pochopil, čili jsem tam dal ten max... funguje to, ale já v tomhle případě žádnej max hledat nepotřebuju... potřebuju prostě jenom id od té zprávy ke které náleží ten poslední čas... takže nedochází tam k nějakému zbytečnému provádění toho max? děkuji za vysvětlení. |
||
Kajman Profil |
#28 · Zasláno: 14. 2. 2014, 22:32:39
Pokud platí, že novější zprávy (větší cas_zpravy_vzkazy_data) mají vždy větší id, tak si dejte max(id_vzkazu_data) místo max(cas_zpravy_vzkazy_data) a celý ten výsledek po limitu dejte do závorky a k tomu přijoinujte ještě jednou tu samou tabulku vzkazy_data podle id.
Případně jde v postgresql použít distinct on. Tam by v poddotazech vypadlo groupování, ale také by se to muselo před limitem zapouzdřit a seřadit podle času. |
||
tečky Profil * |
#29 · Zasláno: 15. 2. 2014, 12:01:31 · Upravil/a: tečky
Kajman:
a k tomu přijoinujte ještě jednou tu samou tabulku vzkazy_data podle id No to přesně jsem taky zkoušel, ale neustále mi to vypisovalo jiná id než mělo. v MySQL to šlo s tim group by snadněji teda. Nevznikala z toho změť provázaných tabulek ve kterejch se přiznám že se už nevyznám. Já už z toho nemůžu!!! pošlu Vám co mám a co potřebuju. nikdy to nepochopim asi! nepochopim proč je groub by propojený s agregačníma funkcema... nic SELECT provazane_id, nick_uzivatele, posledni, dorucenka FROM ( SELECT DISTINCT ON (provazane_id) provazane_id, nick_uzivatele, posledni, dorucenka FROM ( SELECT datova.provazane_id, uzivatelska.nick_uzivatele, MAX (datova.cas) AS posledni, MAX (datova.dorucenka::text) AS dorucenka FROM (( SELECT id_adresat_vzkazy_data AS provazane_id, dorucenka_vzkazy_data AS dorucenka, MAX (cas_zpravy_vzkazy_data) AS cas FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_adresat_vzkazy_data, dorucenka_vzkazy_data ) UNION ALL ( SELECT id_odesilatel_vzkazy_data AS provazane_id, dorucenka_vzkazy_data AS dorucenka, MAX (cas_zpravy_vzkazy_data) AS cas FROM vzkazy_data WHERE id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_odesilatel_vzkazy_data, dorucenka_vzkazy_data ) ) AS datova JOIN uzivatele AS uzivatelska ON datova.provazane_id = uzivatelska.id_uzivatele GROUP BY datova.provazane_id, uzivatelska.nick_uzivatele ORDER BY posledni DESC, dorucenka LIMIT 20 offset ".$cislo_stranky_komunikatoru." ) AS unikatni_komunikace ) AS razeni_dorucenek ORDER BY posledni DESC tohle jsem zbastlil dohromady ani nevim jestli je to správně... ten distinct on taky potřebuje speciální zapousdření takže jsem tam musel dát další select a teď už jenom potřebuju u každý tý zprávy vědět kdo je odesilatel. Nic jinýho. |
||
Časová prodleva: 5 měsíců
|
|||
tečky Profil * |
#30 · Zasláno: 1. 7. 2014, 16:09:26 · Upravil/a: tečky
zdravim... tak jsem se k tomu slavnostně vrátil... s tím že to vyřešim, ale je to fakt zapeklité... mám teď toto :
SELECT specifikace_radku.provazane_id, specifikace_radku.nick, specifikace_radku.posledni, hledana_data.id_adresat_vzkazy_data, dorucenky.dorucenka FROM ( SELECT datova.provazane_id, uzivatelska.nick_uzivatele as nick, MAX (datova.casove_id) AS posledni FROM (( SELECT id_adresat_vzkazy_data AS provazane_id, MAX (id_vzkazu_data) AS casove_id FROM vzkazy_data WHERE id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_adresat_vzkazy_data ) UNION ALL ( SELECT id_odesilatel_vzkazy_data AS provazane_id, MAX (id_vzkazu_data) AS casove_id FROM vzkazy_data WHERE id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_odesilatel_vzkazy_data ) ) AS datova JOIN uzivatele AS uzivatelska ON datova.provazane_id = uzivatelska.id_uzivatele GROUP BY datova.provazane_id, uzivatelska.nick_uzivatele LIMIT 20 OFFSET ".$cislo_stranky_komunikatoru." ) as specifikace_radku JOIN vzkazy_data AS hledana_data ON specifikace_radku.posledni = hledana_data.id_vzkazu_data JOIN ( SELECT MAX (dorucenka_vzkazy_data::text) as dorucenka, id_adresat_vzkazy_data, id_odesilatel_vzkazy_data FROM vzkazy_data WHERE id_adresat_vzkazy_data = ".$_SESSION['id_uzivatele']." OR id_odesilatel_vzkazy_data = ".$_SESSION['id_uzivatele']." GROUP BY id_odesilatel_vzkazy_data, id_adresat_vzkazy_data ) AS dorucenky ON specifikace_radku.provazane_id = dorucenky.id_adresat_vzkazy_data OR specifikace_radku.provazane_id = dorucenky.id_odesilatel_vzkazy_data ORDER BY posledni DESC s tím že to dělá už skoro to co chci, ale má to stále háček a už opravdu teda nevim jestli to celý řešim optimálně... nicméně teď je problém v tom, že může nastat situace, že odesilatel A odešle 11 zpráv ... 10 zpráv je maximum viditelné na jedné stránce příjemce B si přečte těch 10 zpráv na té jedné stránce a odpoví ... a tím pádem se přestane zobrazovat nepřečtená doručenka u té jedenácté zprávy... takže jestli se v tom někdo vyzná a vyřešíto... tak... poděkuji. případně teda se mi zdá že při rozlehlosti takového dotazu je to asi celé blbě... proto by mě zajímalo jak vyřešit ten příklad uvedený na začátku. |
||
Téma pokračuje na další straně.
|
0