login  Naam:   Wachtwoord: 
Registreer je!
 Nota's op tutorial:

Tutorials > MySQL > Joins
Pagina:

Reacties op de tutorial Joins


Offline  timmie_loots
Gepost op: 28 maart 2005 - 00:54
PHP gevorderde

Duidelijk, leuke tut!

Offline  Mokka
Gepost op: 12 april 2005 - 18:22
Onbekend

Letterlijk van PHP hulp!

Offline  Wijnand
Gepost op: 29 september 2005 - 12:31
Moderator

http://www.phphulp.nl/php/tutorials/3/220/401/

:o

Offline  Wim
Gepost op: 24 december 2005 - 12:25
Crew algemeen

praktis voorbeeldje: een forum
  1. <?php
  2. $query = $mysql->query("SELECT forumtopics.id AS t_id, forumtopics.title AS t_title, forumtopics.poster AS t_poster, DATE_FORMAT(forumtopics.datum, '%d-%m-%Y %H:%i:%s') AS t_datum, forumtopics.bericht AS t_bericht, "
  3. . "forumposts.id AS id, forumposts.poster AS poster, DATE_FORMAT(forumposts.datum, '%d-%m-%Y %H:%i:%s') AS datum, forumposts.bericht AS bericht "
  4. . "FROM forumtopics "
  5. . "INNER JOIN forumposts "
  6. . "ON (topic=forumtopics.id) AND (topic='".$_REQUEST['topic']."')"
  7. . "ORDER BY datum ASC");
  8. ?>

Offline  Thomas
Gepost op: 23 januari 2015 - 16:15
Moderator

Citaat:
Een left join gebruik je wanneer er niet direct een relatie (of connectie) hoeft te bestaan tussen de tabellen. Wanneer een auto stilstaat zit er meestal geen bestuurder in en in dat geval krijgt het betreffende veld de waarde NULL.


Dit klopt niet helemaal denk ik. Een betere omschrijving is wellicht: Een LEFT JOIN (tussen twee tabellen A en B) gebruik je wanneer je resultaten op wilt halen uit tabel A en eventueel, als deze bestaan, gerelateerde gegevens (0 of meer records) uit tabel B.

Indien in tabel B geen gerelateerde gegevens aanwezig zijn, bevatten de opgevraagde kolommen van tabel B alle NULL-waarden.

Dit is ook meteen het verschil met een INNER JOIN: bij een INNER JOIN (tussen tabel A en B) moeten in beide tabellen de gegevens aanwezig zijn die voldoen aan de selectie-criteria, anders levert de query geen resultaten op. Bij een LEFT JOIN is er alleen een verplichting dat aan de selectie-criteria van tabel A is voldaan om resultaten (van tabel A) terug te krijgen. Daarnaast krijg je ook de gegevens van tabel B erbij als er records gevonden worden die aan de selectie-criteria van de JOIN-condities voldoen. Maar je krijgt dus op zijn minst de gegevens van tabel A terug.

Het kan voor het resultaat van je query heel veel uitmaken waar je condities in de query opneemt. Als je bijvoorbeeld een extra voorwaarde voor tabel B hebt in een LEFT JOIN query dan zou je deze kunnen opnemen in het ON-gedeelte met een AND, of in het WHERE-gedeelte van je query. Echter, als je een conditie opneemt in het WHERE-gedeelte (in een LEFT JOIN query) dan werkt deze conditie als een INNER JOIN. Als in dat geval niet aan die conditie voldaan wordt levert je query GEEN resultaten op. Als je daarintegen deze conditie opneemt in het ON-gedeelte van je query en de conditie levert geen matches op dan krijg je WEL resultaten. Welke van de twee je moet gebruiken hangt af van wat je verwacht: verwacht je wel resultaten (van tenminste tabel A) of helemaal geen? Deze keuze kan bijvoorbeeld worden bepaald door de code die de query-resultaten verder verwerkt.

Voorbeeld
Stel je hebt twee tabellen: foto_slots en fotos. Voor het gemak gaan we nu even uit van MyISAM, en dus geen InnoDB met gebruikmaking van foreign keys en de hele mikmak (dit zou je wel moeten doen in een echte relationele database, maar omdat dit het voorbeeld zou compliceren laten we dit hier achterwege)

  1. CREATE TABLE foto_slots (
  2. fs_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  3. fs_order INT(1) UNSIGNED NOT NULL,
  4. fs_page_id INT(2) UNSIGNED NOT NULL,
  5. fs_foto_id BIGINT(20) UNSIGNED
  6. ) ENGINE=MyISAM;
  7.  
  8. CREATE TABLE fotos (
  9. ft_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  10. ft_source VARCHAR(255) NOT NULL,
  11. ft_approved BOOL NOT NULL DEFAULT 0
  12. ) ENGINE=MyISAM;


foto_slots is een tabel die onderdeel uitmaakt van een foto-album. Op elke pagina van het album (fs_page_id - deze zou weer naar een pagina-tabel kunnen wijzen) kun je zes foto's plaatsen op voorgespecificeerde posities (fs_order 1 t/m 6). Details van de foto's staan in een aparte tabel (fotos) waar naar verwezen wordt via fs_foto_id. Daarnaast moeten foto's gekeurd worden (ft_approved) om getoond te mogen worden. De code die dit foto-album aanstuurt vult een album per pagina. Hierbij kunnen posities opengelaten worden, een foto-album kan dus bijvoorbeeld als volgt gevuld zijn:

  1. INSERT INTO fotos (ft_source, ft_approved) VALUES
  2. ('001.jpg', 1),
  3. ('002.jpg', 1),
  4. ('003.jpg', 0),
  5. ('004.jpg', 1),
  6. ('005.jpg', 0),
  7. ('006.jpg', 1);
  8.  
  9. INSERT INTO foto_slots (fs_order, fs_page_id, fs_foto_id) VALUES
  10. (1,1,1),
  11. (2,1,2),
  12. (3,1,3),
  13. (4,1,4),
  14. (5,1,5),
  15. (6,1,6);


Oftewel, er zijn 6 foto's geupload op de eerste pagina van het album, en er zijn 4 foto's goedgekeurd (de eerste, tweede, vierde en zesde foto). Twee foto's zijn nog niet goedgekeurd.

Nu wil je een query schrijven die alle gegevens ophaalt van alle posities van pagina 1 van het foto-album, maar je wilt alleen de informatie hebben van foto's wanneer deze goedgekeurd zijn. Nu kan dit ook anders opgelost worden, maar dit illustreert het effect van waar je je condities plaatst.

Omdat het niet of voorhand vaststaat dat alle posities van een pagina zijn ingenomen door een foto is het sowieso verstandig om een LEFT JOIN te gebruiken. De JOIN-conditie om de tabellen aan elkaar te knopen is redelijk evident: fotos.ft_id = foto_slots.fs_foto_id. En je hebt twee extra condities: een foto moet goedgekeurd zijn: f.ft_approved = 1 en de pagina van het album: foto_slots.fs_page_id = 1. Het maakt niet uit waar je de pagina-conditie plaatst want deze zit in de "A tabel" van de LEFT JOIN. Wat wel uitmaakt is waar je de gekeurd-conditie neerzet, omdat deze conditie de "B tabel" van je LEFT JOIN betreft. Afhankelijk van waar je deze conditie plaatst, krijg je een verschillend aantal resultaten:

  1. SELECT s.fs_order, f.ft_id, f.ft_source
  2. FROM foto_slots s
  3. LEFT JOIN fotos f ON (f.ft_id = s.fs_foto_id AND f.ft_approved = 1)
  4. WHERE s.fs_page_id = 1
  5. ORDER BY s.fs_order;


Levert:
  1. +----------+-------+-----------+
  2. | fs_order | ft_id | ft_source |
  3. +----------+-------+-----------+
  4. | 1 | 1 | 001.jpg |
  5. | 2 | 2 | 002.jpg |
  6. | 3 | NULL | NULL |
  7. | 4 | 4 | 004.jpg |
  8. | 5 | NULL | NULL |
  9. | 6 | 6 | 006.jpg |
  10. +----------+-------+-----------+
  11. 6 rows in set (0.00 sec)


Terwijl:
  1. SELECT s.fs_order, f.ft_id, f.ft_source
  2. FROM foto_slots s
  3. LEFT JOIN fotos f ON (f.ft_id = s.fs_foto_id)
  4. WHERE s.fs_page_id = 1
  5. AND f.ft_approved = 1
  6. ORDER BY s.fs_order;


Het volgende resultaat geeft:
  1. +----------+-------+-----------+
  2. | fs_order | ft_id | ft_source |
  3. +----------+-------+-----------+
  4. | 1 | 1 | 001.jpg |
  5. | 2 | 2 | 002.jpg |
  6. | 4 | 4 | 004.jpg |
  7. | 6 | 6 | 006.jpg |
  8. +----------+-------+-----------+
  9. 4 rows in set (0.00 sec)

Pagina:

Enkel aanvullende informatie is welkom. Geen prijzende of afkeurende reacties.
 
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.037s