Mini JOIN HowTo

PHPportalen Forum Index » Databaser
Lägg ett bokmärke på hela tråden
Skapa nytt inlägg   Svara på inlägget Gå till sida 1, 2  Nästa
Visa föregående ämne :: Visa nästa ämne  
Startad av: Meddelande
temptraq
Ex-Moderator



Medlem i: 4779 dagar
Från: Åkersberga
Status: Offline



#238005
Inlägg Skrivet: 2004-11-11 12:57      Ämne: Mini JOIN HowTo Citera

Inledning
När man arbetar med databaser skiljer man på tre olika relationer,
en till många, många till en och många till många. Vad menas med detta då? Jo, om vi tar mitt exempel nedan (kompisar och telefon) så är det en en till många relation. EN kompis kan ha MÅNGA telefonnummer men EN (?!) telefonnummer kan ha EN kompis. Dojjan77´s exempel (actor och movie) är en många till många relation. actor kan ha MÅNGA movie och movie kan ha MÅNGA actor. Eftersom Dojjan77´s exempel är en många till många relation så har han löst det med en "fristående" relationstabell.
I mitt fall, som bara har en en till många relation , räcker det med en foreign key (eller sekundära id).

Tänkte belysa JOIN lite med exempel...

Skapa dessa tabeller i en ny databas:

KOD:
1:
#
2:
# Table structure for table `kompisar`
3:
#
4:
 
5:
CREATE TABLE `kompisar` (
6:
  `id` int(8) NOT NULL auto_increment,
7:
  `förnamn` varchar(20) NOT NULL default '',
8:
  `efternamn` varchar(20) NOT NULL default '',
9:
  PRIMARY KEY  (`id`)
10:
) TYPE=MyISAM AUTO_INCREMENT=5 ;
11:
 
12:
#
13:
# Dumping data for table `kompisar`
14:
#
15:
 
16:
INSERT INTO `kompisar` VALUES (1, 'Kalle', 'Anka');
17:
INSERT INTO `kompisar` VALUES (2, 'Kajsa', 'Anka');
18:
INSERT INTO `kompisar` VALUES (3, 'Musse', 'Pigg');
19:
INSERT INTO `kompisar` VALUES (4, 'Svarte', 'Petter');
20:
 
21:
#
22:
# Table structure for table `telefon`
23:
#
24:
 
25:
CREATE TABLE `telefon` (
26:
  `id` int(8) NOT NULL auto_increment,
27:
  `tillhor_kompis` int(8) NOT NULL default '0',
28:
  `nummer` varchar(20) NOT NULL default '',
29:
  PRIMARY KEY  (`id`)
30:
) TYPE=MyISAM AUTO_INCREMENT=7 ;
31:
 
32:
#
33:
# Dumping data for table `telefon`
34:
#
35:
 
36:
INSERT INTO `telefon` VALUES (1, 1, '08-123');
37:
INSERT INTO `telefon` VALUES (2, 1, '070-123');
38:
INSERT INTO `telefon` VALUES (3, 2, '08-333');
39:
INSERT INTO `telefon` VALUES (4, 2, '070-333');
40:
INSERT INTO `telefon` VALUES (5, 3, '08-654');
41:
INSERT INTO `telefon` VALUES (6, 3, '070-654');


Och nu till övningarna...

Vi har alltså skapat två tabeller, kompisar och telefon.
För att lista alla våra kompisar skriver vi:

KOD:
1:
 
2:
SELECT *
3:
FROM kompisar
4:
 

Resultat:


Inga telefonnummer...
När vi skapade tabellen telefon så skapade vi ett fält som heter tillhor_kompis. I det fältet lagras kompisens id-nummer. Med hjälp av denna relation kan vi nu få ut telefonnummer till våra kompisar.

KOD:
1:
 
2:
SELECT  *
3:
FROM kompisar, telefon // lagt till tabellen telefon
4:
WHERE kompisar.id = telefon.tillhor_kompis // angett relationen
5:
 

Resultat:


Man kan förfina resultatet genom att ange vilka fält som ska hämtas...
KOD:
1:
 
2:
SELECT  kompisar.förnamn, kompisar.efternamn, telefon.nummer
3:
FROM kompisar, telefon
4:
WHERE kompisar.id = telefon.tillhor_kompis
5:
 


VIKTIGT!!!
Om man glömmer att ange relationen, alltså WHERE kompisar.id = telefon.tillhor_kompis, så får man en så kallad cartesian product.
Det innebär att man länkar ALLA poster i kompisar med ALLA poster i telefon. Det kallas också CROSS JOIN eller FULL JOIN. I exemplet har vi fyra (4) kompisar och sex (6) telefonnummer, vilket ger 6*4=24 träffar. Vad händer om man gör en FULL JOIN mellan två tabeller som innehåller 1000 kunder och 3000 ordrar? Jo, man får 1000*3000= 3 miljoner träffar!!!

Naturligvis kan man begränsa med AND för att få ut mer specifika telefonnummer. Använder den förfinade versionen...
KOD:
1:
 
2:
SELECT  kompisar.förnamn, kompisar.efternamn, telefon.nummer
3:
FROM kompisar, telefon
4:
WHERE kompisar.id = telefon.tillhor_kompis
5:
AND kompisar.förnamn = 'kalle'
6:
 

Resultat:


Den uppmärksamme såg att vi i exemplet där vi listade våra kompisars telefonnummer saknade Svarte Petter. Eftersom villkoret (relationen) var
WHERE kompisar.id = telefon.tillhor_kompis så matchas bara kompisar med telefonnummer där telefonnummer finns. Alltså finns inget telefonummer inlagt så får man heller ingen träff.
Vill man hitta ALLA kompisar och se vad som finns i telefontabellen använder man sig av LEFT JOIN (alla poster i vänstra tabellen matchas)
KOD:
1:
 
2:
SELECT  *
3:
FROM kompisar
4:
LEFT JOIN telefon
5:
ON kompisar.id = telefon.tillhor_kompis
6:
 

Resultat:


Användbart för att hitta kompisar vars telefonnummer vi saknar...
KOD:
1:
 
2:
SELECT  *
3:
FROM kompisar
4:
LEFT JOIN telefon
5:
ON kompisar.id = telefon.tillhor_kompis
6:
WHERE telefon.nummer IS NULL
7:
 


Ja, det var det.

-Uppdaterad 2009-09-24 med saknade bilder // Azreal

Senast ändrad av temptraq den 2005-06-02 20:19, ändrad totalt 2 gånger
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
md2perpe
Ex-Moderator



Medlem i: 5113 dagar
Från: Hallonbergen, Kungsbodarna
Status: Offline



#238007
Inlägg Skrivet: 2004-11-11 13:04      Ämne: Citera

Bra initiativ!

Den här tråden kan nog vara lämplig att klistra, men det hade jag visst inte rättigheter att göra trots att jag är moderator här.
 

_________________
6 + sqrt(64) = 10
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
temptraq
Ex-Moderator



Medlem i: 4779 dagar
Från: Åkersberga
Status: Offline



#238010
Inlägg Skrivet: 2004-11-11 13:15      Ämne: Citera

Jo, var inne på Wiki först men kunde inte lista ut hur jag skulle skapa en ny (?) och om det hör till Skola, Artikel osv.
Nu finns den här, sen får väl admin göra sitt Wink
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
dojjan77



Medlem i: 5141 dagar

Status: Offline



#238043
Inlägg Skrivet: 2004-11-11 14:17      Ämne: Citera

Fortsätter lite på SQL-skolan med en klassisk relationsdatabas och vad passar inte bättre en än filmdatabas?

OBS! Jag skulle inte råda någon att göra en egen filmdatabas över sina filmer eftersom det är slöseri med tid när det finns imdb och allmovie

Tre tabeller skapas

actors id och namnet på skådespelaren
KOD:
1:
 
2:
CREATE TABLE `actors` (
3:
  `id` int(11) NOT NULL auto_increment,
4:
  `actor` varchar(32) NOT NULL default '',
5:
  PRIMARY KEY  (`id`),
6:
  UNIQUE KEY `actor` (`actor`)
7:
) TYPE=MyISAM AUTO_INCREMENT=4 ;
8:
 
9:
INSERT INTO `actors` (`id`, `actor`) VALUES (1, 'Henry Fonda');
10:
INSERT INTO `actors` (`id`, `actor`) VALUES (2, 'Marlon Brando');
11:
INSERT INTO `actors` (`id`, `actor`) VALUES (3, 'Al Pacino');
12:
 


movies id och namnet på filmen
KOD:
1:
 
2:
CREATE TABLE `movies` (
3:
  `id` int(11) NOT NULL auto_increment,
4:
  `movie` varchar(32) NOT NULL default '',
5:
  PRIMARY KEY  (`id`),
6:
  UNIQUE KEY `movie` (`movie`)
7:
) TYPE=MyISAM AUTO_INCREMENT=5 ;
8:
 
9:
INSERT INTO `movies` (`id`, `movie`) VALUES (1, '12 Angry Men');
10:
INSERT INTO `movies` (`id`, `movie`) VALUES (2, 'On Golden Pond');
11:
INSERT INTO `movies` (`id`, `movie`) VALUES (3, 'The Godfather');
12:
INSERT INTO `movies` (`id`, `movie`) VALUES (4, 'Scarface');
13:
 


contributors länk mellan film och skådespelare
Notera att movie_id och actor_id är gemensamt satta till PRIMARY KEY
KOD:
1:
 
2:
CREATE TABLE `contributors` (
3:
  `movie_id` int(11) NOT NULL default '0',
4:
  `actor_id` int(11) NOT NULL default '0',
5:
  PRIMARY KEY  (`movie_id`,`actor_id`)
6:
) TYPE=MyISAM;
7:
 
8:
INSERT INTO `contributors` (`movie_id`, `actor_id`) VALUES (0, 0);
9:
INSERT INTO `contributors` (`movie_id`, `actor_id`) VALUES (1, 1);
10:
INSERT INTO `contributors` (`movie_id`, `actor_id`) VALUES (2, 1);
11:
INSERT INTO `contributors` (`movie_id`, `actor_id`) VALUES (3, 2);
12:
INSERT INTO `contributors` (`movie_id`, `actor_id`) VALUES (3, 3);
13:
INSERT INTO `contributors` (`movie_id`, `actor_id`) VALUES (4, 3);
14:
 


Om vi nu vill veta vilka skådespelare som medverkar i filmerna hur gör man då?

KOD:
1:
 
2:
SELECT movie, actor
3:
FROM contributors
4:
INNER JOIN movies ON
5:
    movies.id = movie_id
6:
INNER JOIN actors ON
7:
    actors.id = actor_id
8:
 


Det som händer är att alla rader från contributors joinas med movies och actors om id:et från contributors stämmer överens med det i actors och movies

Om man vill veta vem som är med i Gudfadern, hur gör man då?

KOD:
1:
 
2:
SELECT actor
3:
FROM movies
4:
INNER JOIN contributors ON
5:
    movies.id = movie_id AND
6:
    movie = 'The Godfather'
7:
INNER JOIN actors ON
8:
    actors.id = actor_id
9:
 


Vad är poängen med ovanstående tabellstruktur?

1. Om man vill ändra något i en databas ska man bara behöva göra det på ett ställe. Dvs. om man vill ändra namnet på en film ska man bara behöva göra det i en cell det är därför man har ett id i actors och movies

2. Genom att normalisera sina tabeller så tar de mindre plats. att länka till ett id tar mindre plats än om man skulle länka till hela namnet.

3. Enkelt att utöka, säg att man vill göra en tabell över vilka skådespelare som har haft en relation så är det fixat i en handvändning.

4. Tabellerna kan användas var för sig, säg att man vill lista alla skådisar så är det enkelt gjort med

KOD:
1:
 
2:
SELECT * FROM actors
3:
ORDER BY actor
4:
 


Hoppas att ovanstående är till någon nytta? Har ni några synpunkter eller hittar några felaktigheter så posta gärna dem här!
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
dojjan77



Medlem i: 5141 dagar

Status: Offline



#294478
Inlägg Skrivet: 2005-06-07 16:26      Ämne: Citera

Self-Joins:
http://www.onlamp.com/pub/a/onlamp/2001/07/12/aboutSQL.html

Vilket även leder till om man vill lista t.ex. top 5 från en speciell grupp:
http://www.phpportalen.net/viewtopic.php?p=294328#294328
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
spuun



Medlem i: 4881 dagar
Från: Linköping
Status: Offline



#297412
Inlägg Skrivet: 2005-06-27 18:18      Ämne: Citera

Mera JOIN-skola! Har inte greppat exakt vad INNER och OUTER osv gör ;(
 

_________________
:] :] :] *kjamizzar* :] :] :]

Varför inkludera allt i indexfilen?
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
temptraq
Ex-Moderator



Medlem i: 4779 dagar
Från: Åkersberga
Status: Offline



#297494
Inlägg Skrivet: 2005-06-28 09:12      Ämne: Citera

Utan exempel...
INNER JOIN ger dig bara resultat där det finns träffar i bägge tabellerna.
I exemplet med telefonlista kommer Svarte Petter inte att komma med i resultatet eftersom han saknar telefonnummer.

Tvärt om (!) gör OUTER JOIN (som eg. är LEFT JOIN), alltså det genererar ett resultat som består av alla poster i tabell_1 och dess joinade del från tabell_2 (men det kan vara NULL om det inte finns matchande poster).

Här finns lite mer att läsa, på engelska
http://www.w3schools.com/sql/default.asp
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
spuun



Medlem i: 4881 dagar
Från: Linköping
Status: Offline



#297537
Inlägg Skrivet: 2005-06-28 13:15      Ämne: Citera

temptraq skrev:
Utan exempel...
INNER JOIN ger dig bara resultat där det finns träffar i bägge tabellerna.
I exemplet med telefonlista kommer Svarte Petter inte att komma med i resultatet eftersom han saknar telefonnummer.

Tvärt om (!) gör OUTER JOIN (som eg. är LEFT JOIN), alltså det genererar ett resultat som består av alla poster i tabell_1 och dess joinade del från tabell_2 (men det kan vara NULL om det inte finns matchande poster).

Här finns lite mer att läsa, på engelska
http://www.w3schools.com/sql/default.asp


Ah,tack tack. Gav mig väldigt mycket info trots kort förklaring!
 

_________________
:] :] :] *kjamizzar* :] :] :]

Varför inkludera allt i indexfilen?
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
Tagnard



Medlem i: 4074 dagar
Från: Östersund
Status: Offline



#382734
Inlägg Skrivet: 2006-05-28 19:34      Ämne: Citera

ska det gå att skriva
WHERE kompisar.id = telefon.tillhor_kompis
på alla sql servrar eller krävs det en speciel version Question
 

_________________
<?php $me > $you ? 'I own you!' : 'Hello, sir!' ?>
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
fredd



Medlem i: 4015 dagar

Status: Offline



#385291
Inlägg Skrivet: 2006-06-05 18:18      Ämne: Citera

Ville bara säga tack till tempraq som startade denna tråden.. Äntligen fick jag till mina sql frågor..
Gör bra förklarat!
 

_________________
BIOS: Keyboard error or no keyboard present: press F1 to continue
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
lunner



Medlem i: 4680 dagar
Från: Ronneby
Status: Offline



#390125
Inlägg Skrivet: 2006-06-25 22:37      Ämne: Citera

kan man ha två "where" uttryck i samma sql-sats?
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
paq
Ex-Moderator



Medlem i: 5166 dagar
Från: 59° 19' 6" N, 18° 3' 26" Ö
Status: Offline



#390186
Inlägg Skrivet: 2006-06-25 23:52      Ämne: Citera

lunner skrev:
kan man ha två "where" uttryck i samma sql-sats?

Följ bara upp med AND Smile
KOD:
1:
SELECT * FROM tabell WHERE id = 1 AND name = 'test'


Om detta ska diskuteras vidare så starta då en ny tråd, problemet har inget att göra med den här tråden.
 

_________________
Moderator Kolla Hemsidan
http://www.oscarb.se
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
di98mase



Medlem i: 4535 dagar

Status: Offline



#406150
Inlägg Skrivet: 2006-08-19 22:25      Ämne: men... Citera

vad händer om man tar bort en film ur tabellen 'movies' då har man länkar i contributors som pekar på nått som inte finns? Hur hanterar man det?
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
dixon_



Medlem i: 3819 dagar

Status: Offline



#415113
Inlägg Skrivet: 2006-09-20 10:51      Ämne: Citera

Bakgrund:
Låt oss säga att Kalle och Kajsa har samma hemnummer och olika mobilnummer. Sedan säger vi att Svarte Petter har ett annat hemnummer men samma mobilnummer som Kalle (han har kopierat hans sim-kort Very Happy).

Problemdefinition:
Jag har en lapp med två telefonnummer: ett hemnummer och ett mobilnummer. Jag vill veta VILKEN person som stämmeröverrens med BÅDA nummrena.

Hur ställer man den SQL-frågan så att man får ett korrekt svar? Går det över huvud taget?

Förstod ni min fråga? Razz
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
metalboy



Medlem i: 4699 dagar
Från: Upplands Väsby
Status: Offline



#415125
Inlägg Skrivet: 2006-09-20 12:03      Ämne: Citera

KOD:
... WHERE hemnummer='xxx' AND mobilnummer='yyy'
borde väl fungera?
 

_________________
Vad händer om man stör en utvecklare i hans arbete? - Han blir utvecklingsstörd
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Visa tidigare inlägg:   
Skapa nytt inlägg   Svara på inlägget Gå till sida 1, 2  Nästa
PHPportalen Forum Index » Databaser
Hoppa till:  
Du kan inte skapa nya inlägg i det här forumet
Du kan inte svara på inlägg i det här forumet
Du kan inte ändra dina inlägg i det här forumet
Du kan inte ta bort dina inlägg i det här forumet
Du kan inte rösta i det här forumet
Du kan inte bifoga filer i detta forum
Du kan inte ladda ner filer från detta forum
Kontakta oss på adressen: info@phpportalen.net
Webbplatsen bygger i grunden på phpBB © 2001, 2002 phpBB Group

Modifieringar har senare gjorts i systemet av PHPportalen
Sid och logotypdesign skapad av Daren Jularic