« 1 2 »
Autor Zpráva
tečky
Profil *
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
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
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 *
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
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 *
Tori:
Mé omluvy dámo. A ještě jednou dík. :)))
Kajman
Profil
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
tečky
Profil *
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 *
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
Zapomněla jsem vyhodit to ORDER BY cas_zpravy, opraveno.
tečky
Profil *
no tak teď

ERROR: non-integer constant in ORDER BY
ŘÁDKA 7: ORDER BY NULL)
Tori
Profil
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
Kajman:
Mohla bych ještě poprosit o vysvětlení, proč tam to ORDER BY NULL vyhazovalo chybu?
Kajman
Profil
Tori:
Tak to netuším. Třeba to dělá jen verze nebo konfigurace, co má tečky.
tečky
Profil *
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
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 *
Kajman:
Děkuju Vám za trpelivost. Teď dotaz už funguje. :)
tečky
Profil *
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. Jinak oba vnitřní selecty můžou mít stejnou hodnotu v LIMIT jako ten vnější select. Volba konkrétní stránky výsledků musí být až ve vnějším selectu (výběr 10.–15. záznamu z přijatých a odeslaných zpráv zvlášť může vrátit jiný výsledek než výběr 10.–15. záznamu z předem sloučených dat). Nenapadá mě teď, jak by to šlo zrychlit, možná indexem přes oba sloupce ID odesilatele + čas odeslání, a přes ID adresáta + čas odeslání? Ale to jen hádám.
tečky
Profil *
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
Ve vnitřních dotazech může být
order by cas desc
limit dvacetinásobekcislastrankyplusdvacet
Ale nemusí to vést ke svižnějšímu pojetí dotazu.
tečky
Profil *
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
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 *
Kajman:
děkuji
tečky
Profil *
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
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 *
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.
tečky
Profil *
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.
« 1 2 »

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