05. april 2006 - 23:07Der er
13 kommentarer og 1 løsning
Left JOIN?
Min situation er som følger:
Jeg har to tabeller:
forum_threads: +-----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | header | varchar(255) | NO | | | | | besked | text | NO | | | | | user | int(11) | NO | | 0 | | | time | int(11) | NO | | 0 | | | visninger | int(11) | NO | | 0 | | | forum | int(11) | NO | | 0 | | +-----------+--------------+------+-----+---------+----------------+
forum_readposts: +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | user | int(11) | NO | PRI | 0 | | | traad | int(11) | NO | PRI | 0 | | +-------+---------+------+-----+---------+-------+
forum_threads indeholder som navnet antyder trådene i mit forum. Når en bruger går ind og læser en tråd oprettes der en række i forum_readposts som angiver at brugeren har læst denne tråd.
Jeg ønsker nu at finde alle tråde hvor brugeren ikke har været inde og læse (altså hvor der ikke er noget post i forum_readposts med det bruger ID og den tråds id).
Jeg har prøvet med følgende select, men det virkede ikke: SELECT header, traad FROM forum_threads LEFT JOIN forum_readposts ON forum_threads.id = forum_readposts.traad WHERE forum_readposts.user = 1;
Den ovenstående SQL burde efter min forståelse returnere alle posts, såvel ulæste som læste, men den returnerer kun de læste (som hvis jeg havde lavet en normal join).
Den moderne arbejdsplads er i stigende grad afhængig af mødelokaler til at fremme samarbejde, men dette skift medfører også stigende sikkerhedsudfordringer.
Du skal nok lige have brugerens id med i JOIN-betingelsen:
SELECT header, traad FROM forum_threads LEFT JOIN forum_readposts ON forum_threads.id = forum_readposts.traad AND forum_readposts.user = 1 WHERE forum_readposts.traad IS NULL
Med WHERE.-betingelsen (som arne_v også skrev) får du kun dem, han ikke har læst. Uden får du dem alle - både læste og ikke læste.
Synes godt om
Slettet bruger
06. april 2006 - 12:19#3
Barklund: Jeg kom frem til nogenlunde det samme i nat, men så kom jeg til at tænke på, at du jo ikke kan smide bruger ID med ind, for det er jo meningen at vi skal finde tråde hvor det IKKE ligger...
LEFT JOIN bruges til at finde posts i en tabel også selvom de ikke har noget modstykke i den anden tabel. I mit tilfælde vil jeg jo gerne finde dem som har et modstykke, jeg vil bare kun finde dem som ikke har noget GYLDIGT modstykke, dvs. dem hvor brugeren ikke har læst, altså hvor der ikke ligger noget post hvor traad = forum_threads.id og user = et givent bruger id.
Synes godt om
Slettet bruger
06. april 2006 - 12:26#4
Okay... Jeg har lige fået et syn :)
Her er en SQL sætning der virker:
SELECT header, traad FROM forum_threads LEFT JOIN (SELECT * FROM forum_readposts WHERE user = 1) forum_readposts ON forum_threads.id = forum_readposts.traad WHERE forum_readposts.traad IS NULL;
Virkede min query ikke? For jeg er med på, hvad du ville, men mener nu nok, at min query burde gøre det. Men ja, selvfølgelig kan det klares med en subselect :)
Synes godt om
Slettet bruger
06. april 2006 - 13:57#6
En left join viser NULL i alle felter hvis der ikke er noget modstykke i den anden tabel. Derfor kunne jeg ikke lave forum_readposts.user = 1, da den altid ville være NULL
Men det har jeg jo heller ikke lavet i min query? Jeg har jo netop flyttet WHERE-betingelsen op som en JOIN-betingelse? Jeg ved godt hvordan OUTER og INNER fungerer ;)
Synes godt om
Slettet bruger
06. april 2006 - 14:33#8
Det er fint, men du besvarer så ikke spørgsmålet. Jeg havde brug for alle de posts EN GIVEN BRUGER ikke havde læst :) Og der skal man have fat i et subselect for at det kan komme til at virke :)
Konceptet er jo netop som du selv siger at LEFT JOIN'e med alle dem, som han _har_ læst, og derefter finde dem, der netop kun er på den ene side i dette join. Det er præcis, hvad du ønsker, og præcist hvad min query gør. :(
Synes godt om
Slettet bruger
11. april 2006 - 00:37#11
bark problemet er at lave en while. Din sql finder alle posts som INGEN har læst, men jeg vil jo finde alle som en given bruger ikke har læst.
Det er nu også, hvad jeg mener den bør gøre. Spørgsmålet er ikke så komplekst igen, så jeg regner med at have forstået det hele :)
Jeg har lige testet på en tilsvarende database-design med queryen:
SELECT * FROM film_film LEFT JOIN film_seen ON film_film.f_film_id = film_seen.f_film_id AND film_seen.f_user_id = 1
Altså hvor der er film_seen og film_film og jeg vil finde alle de film, som brugeren med id=1 _ikke_ har set. Og det virker og giver mig de 25 poster.
:)
-- Morten Barklund
Synes godt om
Slettet bruger
20. juni 2006 - 18:40#13
Status er at denne SQL er den jeg bruger: SELECT header, traad FROM forum_threads LEFT JOIN (SELECT * FROM forum_readposts WHERE user = 1) forum_readposts ON forum_threads.id = forum_readposts.traad WHERE forum_readposts.traad IS NULL;
Synes godt om
Slettet bruger
22. august 2006 - 16:48#14
Lukker...
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.