Datele trebuie stocate astfel încât să nu existe informații redundante în baza de date. De exemplu, dacă baza noastră de date include grupuri de persoane care, în fiecare caz, toți urmăresc același hobby, atunci am evita mai degrabă să stocăm în mod repetat aceleași detalii statice despre un anumit hobby; și anume în fiecare înregistrare despre unul dintre pasionații hobby-ului. De asemenea, am evita mai degrabă să stocăm în mod repetat aceleași informații detaliate despre un hobbyist individual, și anume în fiecare înregistrare despre unul dintre hobby-urile acelei persoane. În schimb, creăm tabele independente pentru persoane și hobby și indicăm de la unul la altul. Această tehnică de grupare a datelor în tabele separate, fără redundanță se numește normalizarea bazei de date. O astfel de separare tinde, de asemenea, să simplifice logica și să sporească flexibilitatea asamblarii exacte a articolelor necesare pentru un anumit scop. Acest asamblare se realizează prin operația „JOIN”.
Ideea
În baza noastră de date exemplu, există două tabele: person și contact. Tabelul contact conține coloana person_id, care se corelează cu Primary-Key coloana id din tabelul person. Evaluând valorile coloanei, putem uni contacte și persoane împreună.
tabelul P person
|
tabelul C contact
|
Tabelul unit (virtual), creat din person și contact
P.ID | P.LASTNAME | P.FIRSTNAME | … | C.ID | C.PERSON_ID | C.CONTACT_TYPE | C.CONTACT_VALUE |
---|---|---|---|---|---|---|---|
1 | Goldstein | Larry | … | 1 | 1 | fixed line | 555-0100 |
1 | Goldstein | Larry | … | 2 | 1 | larry.goldstein@acme.xx | |
1 | Goldstein | Larry | … | 3 | 1 | lg@my_company.xx | |
1 | Goldstein | Larry | … | 4 | 1 | icq | 12111 |
2 | Burton | Tom | … | ? | ? | ? | ? |
3 | Hamilton | Lisa | … | ? | ? | ? | ? |
4 | Goldstein | Kim | … | 5 | 4 | fixed line | 5550101 |
4 | Goldstein | Kim | … | 6 | 4 | mobile | 10123444444 |
… | … | … | … | … | … | … | … |
Deci, Larry Goldstein, care există o singură dată în tabelul de persoane stocate, este acum listat de patru ori în tabelul virtual alăturat – de fiecare dată, în combinație cu unul dintre cele patru articole de contact ale sale. Același lucru este valabil și pentru Kim Goldstein și cele două elemente de contact ale sale.
Dar ce se întâmplă cu Tom Burton și Lisa Hamilton, ale căror informații de contact nu sunt disponibile? Este posibil să avem probleme în încercarea de a asocia datele personale cu informațiile lor de contact inexistente. Pentru moment, am semnalat situația cu semne de întrebare. O explicație detaliată a modului de transformare a problemei într-o soluție o discutăm mai târziu.
Sintaxa de bază
Evident că este necesar să specificați două lucruri cu operația JOIN
- denumirile tabelelor relevante
- numele coloanelor relevante
Sintaxa de bază extinde comanda SELECT cu aceste două elemente
SELECT <things_to_be_displayed> -- ca de obicei
FROM <tablename_1> <table_1_alias> -- un alias de tabel
JOIN <tablename_2> <table_2_alias> ON <join condition> -- criteriul de unire
... -- opțional toate celelalte elemente ale comenzii SELECT
;
Să facenm o primă încercare.
SELECT *
FROM person p
JOIN contact c ON p.id = c.person_id;
Unul dintre numele de tabel este referit după cuvântul cheie FROM (ca anterior), iar celălalt după noul cuvânt cheie, JOIN, care (nici o surpriză aici) instruiește SGBD să efectueze o operație de unire. În continuare, cuvântul cheie ON introduce numele coloanelor împreună cu un operator de comparație (sau o condiție generală, după cum veți vedea mai târziu). Numele coloanelor sunt prefixate cu pseudonimele respective ale numelor de tabel, p și c. Acest lucru este necesar deoarece coloanele cu nume identice (cum ar fi id) pot exista în mai multe tabele.
Când DBMS execută comanda, acesta furnizează „ceva” care conține toate coloanele din ambele tabele, inclusiv cele două coloane ID din tabelele respective (person și contact). Rezultatul conține nouă rânduri, unul pentru fiecare combinație existentă de persoană și contact; și anume, din cauza expresiei „ON”, înregistrările persoanei fără înregistrări de contact corespunzătoare nu vor apărea în rezultat.
„Ceva” livrat arată ca un noui tabel; de fapt, are aceeași structură, comportament și date ca un tabel. Dacă este creat dintr-o vizualizare sau ca rezultat al unei subselectări, putem chiar să facem noi SELECT pe el. Dar există o diferență importantă între acesta și un tabel: datele sale asamblate nu sunt stocate în DBMS ca atare; mai degrabă, datele sunt calculate în timpul rulării din valorile tabelelor reale și sunt păstrate doar în memoria temporară în timp ce DBMS rulează programul dumneavoastră.
Această caracteristică cheie – asamblarea de informații complexe din tabele simple – este posibilă prin intermediul celor două cuvinte cheie simple, JOIN și ON. După cum veți vedea, de asemenea, sintaxa poate fi extinsă pentru a construi interogări foarte complexe, astfel încât să puteți adăuga multe rafinări suplimentare la specificațiile criteriilor dvs. de unire.
Uneori poate fi confuz atunci când rezultatele nu se potrivesc cu intențiile tale. Dacă se întâmplă acest lucru, încercați să vă simplificați interogarea, așa cum se arată aici. Confuzia rezultă adesea din faptul că sintaxa JOIN în sine poate deveni destul de complicată. Mai mult, alăturarea poate fi combinată cu toate celelalte elemente sintactice ale comenzii SELECT, ceea ce poate duce, de asemenea, la o lipsă de claritate.
Combinația dintre sintaxa de îmbinare cu alte elemente de limbaj este prezentată în exemplele următoare.
--
-- arata doar coloanele importante
SELECT p.firstname, p.lastname, c.contact_type as "Kind of Contact", c.contact_value as "Call Number"
FROM person p
JOIN contact c ON p.id = c.person_id;
-- arata doar rândurile importante
SELECT p.firstname, p.lastname, c.contact_type as "Kind of Contact", c.contact_value as "Call Number"
FROM person p
JOIN contact c ON p.id = c.person_id
WHERE c.contact_type IN ('fixed line', 'mobile');
-- aplica orice ordine de sortare
SELECT p.firstname, p.lastname, c.contact_type as "Kind of Contact", c.contact_value as "Call Number"
FROM person p
JOIN contact c ON p.id = c.person_id
WHERE c.contact_type IN ('fixed line', 'mobile')
ORDER BY p.lastname, p.firstname, c.contact_type DESC;
-- utilizați funcții: min() / max() / count()
SELECT count(*)
FROM person p
JOIN contact c ON p.id = c.person_id
WHERE c.contact_type IN ('fixed line', 'mobile');
-- JOIN un tabel cu sine însuși. Exemplu: Căutați persoane diferite cu același nume de familie
SELECT p1.id, p1.firstname, p1.lastname, p2.id, p2.firstname, p2.lastname
FROM person p1
JOIN person p2 ON p1.lastname = p2.lastname -- for the second incarnation of person we must use a different alias
WHERE p1.id != p2.id
-- sortarea p2.lastname nu este necesară deoarece este identică cu p1.lastname deja sortată
ORDER BY p1.lastname, p1.firstname, p2.firstname;
-- JOIN mai mult de două tabele. Exemplu: informații de contact ale diferitelor persoane cu același nume de familie
SELECT p1.id, p1.firstname, p1.lastname, p2.id, p2.firstname, p2.lastname, c.contact_type, c.contact_value
FROM person p1
JOIN person p2 ON p1.lastname = p2.lastname
JOIN contact c ON p2.id = c.person_id -- contact info from person2. p1.id would lead to person1
WHERE p1.id != p2.id
ORDER BY p1.lastname, p1.firstname, p2.lastname;
(Include texte din Wikibooks traduse și adaptate de Nicolae Sfetcu)
Lasă un răspuns