Autor Zpráva
anonymníí
Profil *
Ahoj, řeším v dotazu problém, který pro mnohé bude asi banální, ale nenapadá mě, pod čím hledat.

Kód:
SELECT sloupce
FROM uzivatele u
JOIN clanky c
    ON u.id = c.id
JOIN komentare k
    ON k.article_id = c.id -- tady je problém, pokud k článku není komentář, z výsledků dotazu se mi celý článek vyloučí (není splněna ta podmínka v JOIN ON). Jak vybrat i ty články, které žádné komentáře nemají? 
WHERE ...

Chyba je jasná, nemá zde být samotný JOIN, ale něco k němu. Zkoušel jsem INNER, OUTER, ale nic k výsledku nevedlo.

PS. máte nějaký dobrý tip na www článek, kde bych si mohl o tomto něco více přečíst? Kdy jaký JOIN použít? Moc by mi to pomohlo, pokud se bude jednat o prověřený zdroj informací.

Díky.
juriad
Profil
LEFT JOIN je to co hledáš. Rozepíšu se o tom.
anonymníí
Profil *
juriad:
To jsem si tak nějak podvědomě myslel taky, ale
SELECT sloupce
FROM uzivatele u
JOIN clanky c
    ON u.id = c.id
LEFT JOIN komentare k
    ON k.article_id = c.id 
WHERE ...
mi stále vrací jen ty články, které mají nějaký komentář.
juriad
Profil
Tomu nevěřím. Ukaž úplně celý dotaz.
anonymníí
Profil *
SELECT     u.id,
        u.jmeno,
        u.prijemni,
        c.titulek,
        c.text,
        k.clanek_id,
        k.uzivatel_id
FROM uzivatele u
JOIN clanky c
    ON c.id = u.id
LEFT JOIN komentare k
    ON c.id = k.clanek_id
WHERE     `active` = 1 AND
        u.id = 1 AND
        c.uzivatel_id = 1 AND
        k.uzivatel_id = 1 AND
        u.url = 'url-uzivatele'
ORDER BY     c.datum DESC,
            c.id DESC");



pardon, oprava

SELECT  u.id,
        u.jmeno,
        u.prijemni,
        c.titulek,
        c.text,
        k.clanek_id,
        k.uzivatel_id
FROM uzivatele u
JOIN clanky c
    ON c.uzivatel_id = u.id
LEFT JOIN komentare k
    ON c.id = k.clanek_id
WHERE     `active` = 1 AND
        u.id = 1 AND
        c.uzivatel_id = 1 AND
        k.uzivatel_id = 1 AND
        u.url = 'url-uzivatele'
ORDER BY     c.datum DESC,
            c.id DESC
juriad
Profil
Obecně v Myslq existují jen následující.
Podle typu spojení:
JOIN ... podmínka - záznam na obou stranách musí existovat
LEFT JOIN ... podmínka - záznam na levé straně musí existovat; na pravé nemusí
RIGHT JOIN ... podmínka - to samé jako LEFT join ale na druhou stranu (obvykle se nepoužívá)
FULL JOIN ... podmínka - neexistuje (vrátil by i uživatele bez komentářů i komentáře bez uživatelů)

Modifikátory a alternativní zápisy:
CROSS JOIN je speciální typ obyčejného JOINu; používá se tehdy, když nechceš uvádět podmínku (propojí všechny záznamy se všemi)
INNER JOIN je přesně to samé jako obyčejný JOIN; slovo INNER jen zdůrazňuje nutnost existence na obou stranách
NATURAL ... JOIN říká, že spojení se provádí rovností na všech sloupcích, které mají stejný název
LEFT OUTER JOIN, RIGHT OUTER JOIN - to samé jako bez OUTER; slovo OUTER jen zdůrazňuje, že jedna ze stran nemusí existovat
STRAIGHT_JOIN ... - to samé jako obyčejný JOIN, ale řeší optimalizaci dotazu, pokud by se engine mysql rozhodl špatně (není důvod používat)

Dokumantace:
http://dev.mysql.com/doc/refman/5.6/en/join.html

[INNER | CROSS] JOIN table_factor [join_condition]
STRAIGHT_JOIN table_factor
STRAIGHT_JOIN table_factor ON conditional_expr
{LEFT|RIGHT} [OUTER] JOIN table_reference join_condition
NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor
anonymníí
Profil *
uživatel s ID=1 napsal 3 články, ke dvě jsou komentáře. A dotaz vrací jen ty dva, nekomentovaný článek nezobrazí.
Kajman
Profil
anonymníí:
Podmínka na k.uzivatel_id = 1 patří do on klauzule, ne do where
anonymníí
Profil *
juriad:
Už to mám, ve WHERE přebývá k.uzivatel_id - když není kmentář, ta podmínka nemůže být splněna.

Díky, dobral jsem s k tomu po tévm vysvětlení JOINů, které mi pomohlo.
juriad
Profil
Problém je v 16. řádku. Pokud komentář neexistuje, tak přece pro takový řádek nemůže platit, že k.uzivatel_id = 1.
Presuň tu podmínku na 12. řádek.

Mimochodem, proč zadáváš u.url, když znáš přímo id uživatele?
Raději u active napiš, ze které tabulky pochází, takto to není zřejmé, přestože takto pojmenovaný sloupec je jen v jedné.

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: