Јоин (СQЛ)
SQL придруживање клаузула комбинује записе из две или више табела у референтне базе података. Креира сет који може бити снимљен као табела или искоришћен такав какав јесте. ПРИДРУЖИВАЊЕ
је средство за комбиновање поља из две табеле (или више) користећи сродне вредности. ANSI-стандард SQL одређује пет типоваПРИДРУЖИВАЊА
: УНУТРАШЊЕ
, ЛЕВО СПОЉАШЊЕ
, ДЕСНО СПОЉАШЊЕ
, ПОТПУНО СПОЉАШЊЕ
и УКРШТЕНО
. Као специјалан случај, табела (базна табела, преглед, или придружена табела) може придружити
себе у самопридруживање.
Програмер пише наредбу ПРИДРУЖИВАЊА
за идентификацију записа за придруживање. Ако је израчунати предикат тачан, комбиновани запис је онда произведен у очекиваном формату, скуп записа или привремена табела.
Пробне табеле
[уреди | уреди извор]Релационе базе података су обично нормализоване да елиминишу дуплирање података као што су када објекти имају једну-на-више релација. На пример , Одељење може бити повезано са великим бројем Запослених. Придруживање раздваја табеле за Одељење и Запослене и ефективно креира другу табелу која комбинује информације из обе. Ово је у неку штету у смислу времена које је потребно да се израчуна придруживање. А такође је могуће да се једноставно одржава денормализована табела ако је брзина битна, дуплиране информације могу узети додатан простор, и додати трошкове и сложеност одржавања интегритета података ако се подаци који су дуплирани касније промене.
Сва накнадна објашњења о типу придруживања у овом артиклу су направљена на основу следеће две табеле. Редови у овим табелама служе да илуструју ефекат различитих типова придруживања и предиката придруживања. У наредним табелама ОдељењеИД
колона табеле Одељења
(која се може означити као Одељење.ОдељењеИД
) је примарни кључ, док је Запослени.ОдељењеИД
Страни кључ.
Презиме | ОдељењеИД |
---|---|
Раферти | 31 |
Џоунс | 33 |
Хаизенберг | 33 |
Робинсон | 34 |
Смит | 34 |
Вилиамс | NULL |
ОдељењеИД | ОдељењеНазив |
---|---|
31 | Распродаја |
33 | Инжењери |
34 | Свештеници |
35 | Маркетинг |
Напомена: У табели Запослених изнад, запослени "Вилиамс" није још додељен ниједном одељењу. Такође, приметите да нема запослених додељених "Маркетинг" одељењу .
Ово је SQL наредба за креирање наведених табела.
CREATE TABLE одељење
(
ОдељењеИД INT,
ОдељењеНазив VARCHAR(20)
);
CREATE TABLE запослени
(
Презиме VARCHAR(20),
ОдељењеИД INT
);
INSERT INTO одељење VALUES(31, 'Распродаја');
INSERT INTO одељење VALUES(33, 'Инжењери');
INSERT INTO одељење VALUES(34, 'Свештеници');
INSERT INTO одељење VALUES(35, 'Маркетинг');
INSERT INTO запослени VALUES('Раферти', 31);
INSERT INTO запослени VALUES('Џоунс', 33);
INSERT INTO запослени VALUES('Хаизенберг', 33);
INSERT INTO запослени VALUES('Робинсон', 34);
INSERT INTO запослени VALUES('Смит', 34);
INSERT INTO запослени VALUES('Вилиамс', NULL);
Укрштено придруживање
[уреди | уреди извор]УКРШТЕНО ПРИДРУЖИВАЊЕ враћа Декартов производ редова табеле придруживања. Другим речима, произвешће редове који комбинују сваки ред прве табеле са сваким редом друге табеле.[1]
Пример експлицитног укрштеног придруживања:
SELECT *
FROM запослени CROSS JOIN одељење;
Пример имплицитног укрштеног придруживања:
SELECT *
FROM запослени, одељење;
Запослени.Презиме | Запослени.ОдељењеИД | Одељење.ОдељењеНазив | Одељење.ОдељењеИД |
---|---|---|---|
Раферти | 31 | Распродаја | 31 |
Џоунс | 33 | Распродаја | 31 |
Хаизенберг | 33 | Распродаја | 31 |
Смит | 34 | Распродаја | 31 |
Робинсон | 34 | Распродаја | 31 |
Вилиамс | NULL | Распродаја | 31 |
Раферти | 31 | Инжењери | 33 |
Џоунс | 33 | Инжењери | 33 |
Хаизенберг | 33 | Инжењери | 33 |
Смит | 34 | Инжењери | 33 |
Робинсон | 34 | Инжењери | 33 |
Вилиамс | NULL | Инжењери | 33 |
Раферти | 31 | Свештеници | 34 |
Џоунс | 33 | Свештеници | 34 |
Хаизенберг | 33 | Свештеници | 34 |
Смит | 34 | Свештеници | 34 |
Робинсон | 34 | Свештеници | 34 |
Вилиамс | NULL | Свештеници | 34 |
Раферти | 31 | Маркетинг | 35 |
Џоунс | 33 | Маркетинг | 35 |
Хаизенберг | 33 | Маркетинг | 35 |
Смит | 34 | Маркетинг | 35 |
Робинсон | 34 | Маркетинг | 35 |
Вилиамс | NULL | Маркетинг | 35 |
Укрштено придруживање не примењује предикат за филтрирање података из табеле придруживања. Резултат укрштеног придруживања може бити филтриран користећи WHERE
клаузулу која може произвести еквивалент унутрашњег придруживања.
У SQL:2011 стандарду, укрштена придруживања су део опционог F401, "Табела продуженог придруживања", пакета.
Нормална употреба је за проверавање перформанси сервера.
Природно придруживање (⋈)
[уреди | уреди извор]Природно придруживање () је бинарна операција која се записује као (R S) где су R и S релације.[2] Резултат природног придруживања је сет свих комбинација од торки у R и S који су једнаки уобичајеним именима њихових атрибута. На пример размотримо табеле Запослени and Одељење и њихово природно придруживање:
|
|
|
Ово такође може бити искоришћено за дефинисање композиције релација. На пример, композиција Запослени and Одељење је њихово придруживање као што је приказано горе, пројектовано на све сем заједничког атрибута ОдељењеНазив. У теорији категорије, придруживање је управо продукат влакана.
Природно придруживање је вероватно једна од најбитнијих операција јер је релациони пандан логичком И. Приметите пажљиво да ако се иста променљива појављује у сваком од два предиката који су повезани са И, онда се та променљива залаже за исту ствар и оба појављивања морају бити замењена истом вредношћу. Конкретно, природно придруживање омогућује комбинацију релација које су повезане страним кључем. На пример, у горњем примеру страни кључ вероватно раздваја Запослени.ОдељењеНазив и Одељење.ОдељењеНазив и онда природно придруживање Запослених и Одељења комбинује све запослене са њиховим одељењем. Приметите да ово функционише зато што страни кључ стоји између атрибута са истим именом. Ако ово није случај да је страни кључ између Одељење.менаџер и Запослени.Име онда морамо да преименујемо колоне пре него што применимо природно придруживање. Такво придрживање се понекад поистовећује са изједначеним придруживањем.
Више формалне семантике природног придруживања је дефинисано на следећи начин:
где је Fun предикат који је тачан за релацију r Ако и само ако је r функција. Обично се захтева да R и S имају бар једну заједничку особину, али ако се изостави ово ограничење, и R и S немају заједничку особину, онда природно придруживање постаје баш Декартов производ.
Природно придруживање може бити симулирано са Codd's primitives на следећи начин. Претпоставимо да су c1,...,cm имена атрибута заједничка за R и S, r1,...,rn су имена атрибута јединствена за R и s1,...,sk су атрибути јединствени за S. Штавише, претпоставити да имена атрибута x1,...,xm нису ни у R ни у S. У првом кораку ми сада можемо преименовати заједничка имена атрибута у S:
Онда ћемо узети Декартов производ и изабрати оне врсте које треба придружити:
Коначно узимамо пројекцију како би се отарасили преименованих атрибута:
Природно придруживање је специјалан случај изједначеног придруживања које је специјалан случај унутрашњег придруживања као што је описано у Природном придруживању.
Унутрашње придруживање
[уреди | уреди извор]Унутрашње придруживање захтева да сваки податак из две повезане табеле има податак са којим је повезан, и обично је корисна операција у апликацијама али није засигурно најбољи избор у свим ситуацијама. Унутрашње придруживање креира нову резултујућу табелу комбиновањем вредности колона две табеле (A и B) заснованим на предикатима придруживања. Упит пореди сваки ред из А са сваким редом из B како би нашао све парове редова који задовољавају предикат придруживања. Када је предикат придруживања задовољен одговарајућим не-нула вредностима, вредности колона за сваки одговарајући пар редова A и B се комбинују у резултујући ред.
Резултат придруживања може бити дефинисан као исход узимања Декартовог производа (или укрштеног придруживања) свих података табеле (комбиновање сваког податка из табеле А са сваким податком из табеле B) и затим се враћају сви подаци који задовољавају предикат придруживања. Актуелне SQL имплементације нормално користе и друге приступе, као што је [[хеш придруживање или придруживање сортирање спајањем, од ере компјутера Декартов производ је спорији и често ће захтевати недопустиво велики меморијски простор за складишћење.
SQL наводи два различита синтаксна начина да изрази придруживања: "експлицитна нотација придруживања" и "имплицитна нотација придруживања". Такође "имплицитна нотација придруживања" је превазиђена у 1992, и њена употреба се не сматра најбољом праксом, ипак база података је и даље подржава.
"Експлицитна нотација придруживања" користи JOIN
кључну реч, опционо претходи кључној речи INNER
, да одреди табелу придруживања, и ON
кључна реч да одреди предикате за придруживање, као у наредном примеру:
SELECT *
FROM запослено
INNER JOIN одељење ON запослени.ОдељењеИД = одељење.ОдељењеИД;
"Имплицитна нотација придруживања" једноставно листа табеле за придруживања, у FROM
клаузули изјаве SELECT
, користећи зарезе да их раздвоји. Тако се прецизира укрштено придруживање, и WHERE
клаузула може аплицирати додатне филтер-предикате (која функција је упоредива са предикатима придруживања у експлицитној нотацији).
Наредни пример је еквивалентан претходном, али овај пут у имплицитној нотацији:
SELECT *
FROM запослени, одељење
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД;
Упити дати у примерима изнад ће придружити табеле Запослени и Одељење користећи ОдељењеИД колону обе табеле. Где се ОдељењеИД ових табела подудара (тј. предикат придруживања је задовољен), упит ће комбиновати Презиме, Одељење и ОдељењеНазив колоне из две табеле у резултујући ред. Где се ОдељењеИД не подудара, резултујући ред неће бити генерисан.
Тако ће резултат извршења било која од два упита изнад бити:
Запослени.Презиме | Запослени.ОдељењеИД | Одељење.ОдељењеИме | Одељење.ОдељењеИД |
---|---|---|---|
Робинсон | 34 | Свештеници | 34 |
Џоунс | 33 | Инжењери | 33 |
Смит | 34 | Свештеници | 34 |
Хаизенберг | 33 | Инжењери | 33 |
Раферти | 31 | Распродаја | 31 |
Приметимо да се запослени "Вилиамс" и одељење "Маркетинг" не појављују у резултатима извршења упита. Ни једно од њих нема подударања записа у другој одговарајућој табели: "Вилиамс" нема повезано одељење, и нема запослених са одељењем ИД 35 ("Маркетинг"). Зависно од жељених резултата, ово понашање може бити суптилна грешка, која се може избећи заменом унутрашњег придруживања са спољашњим.
Приметити: Програмери би требало посебно да обрате пажњу када табеле придруживања у колонама могу да садрже NULL вредности, док NULL неће никада одговарати било којој другој вредности (ни самој нули), осим ако услов придруживања експлицитно користи комбинацију предиката који прво проверавају да ли су поља придруживања NOT NULL
пре примене преосталих предиката услова. Унутрашње придруживање може једино бити сигурно искоришћен у базама података које спроводе Референцијални интегритет или где поља придруживања гарантовано нису NULL. Многе обраде трансакција релационих база података ослањају се на ACID стандард ажурирања података како би осигурали интегритет података, где унутрашње придруживање постаје одговарајући избор. Међутим трансакција база података обично има пожељна поља придруживања којима је дозвољено да буду NULL. Многе извештајне релационе базе података и складишта података користе висок опсег Extract, Transform, Load (ETL) batch updates који чине референцијални интегритет тешким или немогућим за спровођење, резултује потенцијална NULL поља придруживања која аутор SQL упита не може да модификује и узрокује да унутрашње придруживање изостави податке без индикације о грешци. Избор унутрашњег придруживања зависи од дизајна базе података и карактеристике података. Лево спољашње придруживање може бити замењено унутрашњим када поље придруживања у једној табели може садржати NULL вредности.
Било које поље податка које може бити NULL (празно) не би требало никад да буде употребљено као веза у унутрашњем придруживању, осим ако је жељени резултат да се елиминишу подаци са NULL вредношћу. Ако су NULL поља придруживања намерно уклоњена из скупа резултата,унутрашње придруживања може бити брже од једног спољашњег зато што табела придруживања и филтрирање се обавља у једном кораку. Супротно, унутрашње придруживања може резултирати катастрофалном смањивању перформанси или чак падом сервера при коришћењу великог опсега упита у комбинацији са функцијама базе података у SQL Where клаузули.[3][4][5] Фунција у SQL Where клаузули може резултирари у бази података игнорисањем релативно компактних индекса табеле. База података може читати и селектована поља унутрашњег придруживања из обе табеле пре редуковања броја редова користећи филтер који зависи од израчунате вредности, што резултира релативно огромној количини неефикасне обраде.
Када је резултујући скуп произведен придруживањем више табела, укључујући мастер табеле које се користе за тражење целокупног текстуалног описа нумеричких идентификационих кодова (Лукап табела), а NULL вредности у било ком од страних кључева може резултирати да се цео ред елиминише из резултујућег скупа, без индикације о грешци. Комплекс SQL упита који укључују један или више унутрашњих придруживања и неколико спољашњих имају исти ризик за NULL вредности у линк пољима спољашњег придруживања.
Посвећеност SQL коду садржи претпоставку унутрашњег придруживања да NULL поља придруживања неће бити уведена будућим променама, укључујући vendor updates, промене дизајна и главно процесирање ван правила ваљаности апликационих података као што су конверзије података, миграције, bulk укључивања и стапања.
Може се даље класификовати унутрашње придруживања као изједначено придруживање, као природно придруживања, или као укрштено придруживања.
Изједначено придруживање
[уреди | уреди извор]Изједначено придруживање је специјалан тип придруживања базираног на компаратору, који користи само једнакост поређења у предикату придруживања. Користећи друге операторе поређења (као што је <
) дисквалификује придруживање као изједначено придруживање. Упит приказан горе већ предцтавља пример једног изједначеног придруживања:
SELECT *
FROM запослени JOIN одељење
ON запослени.ОдељењеИД = одељење.ОдељењеИД;
Можемо писати изједначено придруживање као испод,
SELECT *
FROM запослени, одељење
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД;
Ако колоне у изједначеном придруживања имају исто име, SQL-92 допушта опциону скраћену нотацију за изражавање изједначеног придруживања, путем USING
конструкта:[6]
SELECT *
FROM запослени INNER JOIN одељење USING (DepartmentID);
USING
конструкт је више од самог синтактичког шећера (syntactic sugar), ма како, јер се резултујући скуп разликује од резултујућег скупа верзије са експлицитним предикатом. Посебно, било које колоне поменуте у USING
листи ће се појавити само једном, са неквалификованим именом, а по једном за сваку табелу у придруживању. У случају изнад, биће само ОдељењеИД
колона а не запослени.ОдељењеИД
или одељење.ОдељењеИД
.
USING
клаузула није подржана од стране MS SQL Server и Sybase.
Природно придруживање
[уреди | уреди извор]Природно придруживање је врста подједнаког придруживања где join предикат настаје имплицитно поређењем свих колона у обе табеле које имају исти назив колоне у повезаној табели. Резултујућа повезана табела садржи само једну колону за сваки пар колона са истим називом. У случају да нема колона са истим називом онда се користи укрштено придруживање.
Многи експерти сматрају да је ПРИРОДНО ПРИДРУЖИВАЊЕ опасно и обесхрабрује њихову употребу.[7] Опасност долази од намерног додавања нове колоне, именоване исто као друга колона у другој табели. У постојећем природном придруживању он ће "природно" да користи нову колону за поређење, вршећи поређење користећи другачије критеријуме (од различитих колона) него раније. Тако постојећи упит може произвести различите резултате, иако подаци у табели нису промењени, али јесте аргумент. Употреба имена колона да се аутоматски одреди везе између табела није добра опција у великим базама података са стотине или хиљаде табела. У реаланом свету база података су углавном дизајниране са Страни кључ подацима који нису дословно попуњени (NULL вредности су дозвољене), због правила пословања. То је уобичајена пракса да се модификују имена колона сличних података у различитим табелама и овај недостатак природног придруживања је теоретски концепт за дискусију.
Горњи пример упита за унутрашње придруживање може се објаснити као природно придруживање на следећи начин:
SELECT *
FROM запослени NATURAL JOIN одељење;
Као и код експлицитног коришћења USING
клаузуле, само једна ОдељењеИД колона се јавља у придруженој табели:
ОдељењеИД | Запослени.Презиме | Одељење.ОдељењеНазив |
---|---|---|
34 | Смит | Свештеници |
33 | Џоунс | Инжењери |
34 | Робинсон | Свештеници |
33 | Хаизенберг | Инжењери |
31 | Раферти | Распродаја |
PostgreSQL, MySQL и Oracle подржавају природно придруживање; Microsoft T-SQL и IBM DB2 не подржавају. Колоне које се користе у придруживању су имплицитне па код придруживања не приказује очекиване колоне, и промене у називу колона могу да промене разултат. У SQL:2011 стандарду, природно придруижвање је део опције F401, "Проширене табеле придруживања", пакета.
У многим окружењима база података имена колона су контролисана спољашњом помоћу, а не упитом програмера. Природно придруживање претпоставља стабилност и конзистентност назива колона које може да се проемни надоградњом верзије.
Спољашње придруживање
[уреди | уреди извор]Придружене табеле задржавају сваки податак—чак иако не постоји ни један други повезани податак. Спољашње придруживање се даље дели на лево спољашње, десно спољашње придруживање и потпуно спољашње придруживање, што зависи који редови табеле су задржани (леви, десни, или оба).
(У случају лево и десно односи се на две стране JOIN
кључне речи.)
Не постоји имплицитна нотација за спољашње придруижвање у стандарду SQL.
Лево спољашње придруживање
[уреди | уреди извор]Резултат левог спољашњег придруживања (или једноставно лево придруживање) за табеле А и Б увек садржи све податке о “левој” табели (А), чак иако се по услову-придруживања не поклапа са подацима у “десној” табели (Б). Ово значи и ако клаузула ON пронађе 0 података у Б (за задати податак из А), придруживање ће свакако вратити ред као резултат (за тај податак) - али са NULL у свакој колони за Б. Лево спољашње придруживање враћа све вредности из унутрашњег придруживањаа плус све вредности из леве табеле које нису повезане са десном табелом, укључујући редове са NULL (празне) вредностима.
На пример то нам омогућава да пронађемо одељење запослених, али и даље приказује запослене који нису придружени одељењу (за разлику од унутрашњег придруживања пример горе, где непридружени нису били у резултату).
Пример левог спољашњег придруживања
Пример левог спољашњег придруживања ( СПОЉАШЊЕ
кључна реч је опциона), са додатним резултатима реда (у поређењу са унутрашњим придруживањем) су искошени:
SELECT *
FROM запослени
LEFT OUTER JOIN одељење ON запослени.ОдељењеИД = одељење.ОдељењеИД;
Запослени.Презиме | Запослени.ОдељењеИД | Одељење.ОдељењеНазив | Одељење.ОдељењеИД |
---|---|---|---|
Џоунс | 33 | Инжењери | 33 |
Раферти | 31 | Распродаја | 31 |
Робинсон | 34 | Свештеници | 34 |
Смит | 34 | Свештеници | 34 |
Вилиамс | NULL | NULL | NULL |
Хаизенберг | 33 | Инжењери | 33 |
Алтернативне синтаксе
[уреди | уреди извор]Oracle подржава застарелу[8] синтаксу:
SELECT *
FROM запослени, одељење
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД(+)
Sybase подржава синтаксу (Microsoft SQL Server старија синтакса од верзије 2000):
SELECT *
FROM запослени, одељење
WHERE запослени.ОдељењеИД *= одељење.ОдељењеИД
IBM Informix подржава синтаксу:
SELECT *
FROM запослени, OUTER одељење
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД
Десно спољашње придруживање
[уреди | уреди извор]Десно спољашње придруживање (или десно придруживање) личи на лево спољашње придруживање, осим што табеле третира обрнуто. Сваки ред из "десне" табеле (Б) ће се појавити у придруженој табели барем једном. Уколико постоје неповезани редови из "леве" табеле (А), NULL ће се појавити у колони из А за оне податке који нису повезани са Б.
Десно спољашње придруживање враћа све вредности из десне табеле и повезане вредности из леве табеле (NULL у случају да није повезан придружује предикат). На пример, ово нам омогућава да нађемо запослене и његово или њено одељење, али и даље показује одељења које немају запослене.
Испод је пример десно спољашњег придруживања (СПОЉАШЊЕ
кључна реч је опциона), са додатним редом резултата који је искошен:
SELECT *
FROM запослени RIGHT OUTER JOIN одељење
ON запослени.ОдељењеИД = одељење.ОдељењеИД;
Запослени.Презиме | Запослени.ОдељењеИД | Одељење.ОдељењеНазив | Одељење.ОдељењеИД |
---|---|---|---|
Смит | 34 | Свештеници | 34 |
Џоунс | 33 | Инжењери | 33 |
Робинсон | 34 | Свештеници | 34 |
Хаизенберг | 33 | Инжењери | 33 |
Раферти | 31 | Распродаја | 31 |
NULL | NULL | Маркетинг | 35 |
Десно и лево спољашње придруживање су функционално једнаки. Ни један нема неку функцију коју други нема, тако да десно и лево спољашње придруживање могу да замене једно друго све док је редослед у табели обрнут.
Потпуно спољашње придруживање
[уреди | уреди извор]Концептуално, потпуно спољашње придруживање комбинује ефекте од примене оба и левог и десног спољашњег придруживања. Где подаци у табели потпуног спољашњег придруживања нису повезани, резултат ће имати NULL вредност за сваку колону у табели где недостсаје повезани ред. За те податке који се поклапају, резултата ће бити једна линија (садржи поља из обе табеле).
На пример, ово нам омогућава да видимо сваког запосленог који је у одељењу и свако одељење које има неког запосленог, али и да видимо сваког запосленог који није део одељења и свко одељење које нема запосленог.
Пример тоталног спољашњег придруживања (СПОЊАШЊЕ
кључна реч је опциона):
SELECT *
FROM запослени FULL OUTER JOIN одељење
ON запослени.ОдељењеИД = одељење.ОдељењеИД;
Запослени.Презиме | Запослени.ОдељењеИД | Одељење.ОдељењеНазив | Одељење.ОдељењеИД |
---|---|---|---|
Смит | 34 | Свештеници | 34 |
Џоунс | 33 | Инжењер | 33 |
Робинсон | 34 | Свештеници | 34 |
Вилиамс | NULL | NULL | NULL |
Хаизенберг | 33 | Инжењер | 33 |
Раферти | 31 | Распродаја | 31 |
NULL | NULL | Маркетинг | 35 |
Неке базе података не подржавају функције тоталног спољашњег придруживања директно, али могу да симулирају то кроз употребу унутрашњег придруживања и UNION ALL селектора за "појединачни ред табеле" од леве и десне табеле редом. Исти пример може да се прикаже на следећи начин:
SELECT запослени.Презиме, запослени.ОдељењеИД,
одељење.ОдељењеНазив, одељење.ОдељењеИД
FROM запослени
INNER JOIN одељење ON одељење.ОдељењеИД = одељење.ОдељењеИД
UNION ALL
SELECT запослени.Презиме, запослени.ОдељењеИД,
cast(NULL as varchar(20)), cast(NULL as integer)
FROM запослени
WHERE NOT EXISTS (
SELECT * FROM одељење
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД)
UNION ALL
SELECT cast(NULL as varchar(20)), cast(NULL as integer),
одељење.ОдељењеНазив, одељење.ОдељењеИД
FROM одељење
WHERE NOT EXISTS (
SELECT * FROM запослени
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД)
Самопридруживање
[уреди | уреди извор]Самопридруживање придружује табелу себи.[9]
Пример
[уреди | уреди извор]Уколико имамо две одвојене табеле за запослене и питање које захтева запосленог у првој табели који има исту државу као и запослен у другој табели, нормално придруживање може да се користи за налажење одговора. Свакако, све информације за запосленог се налазе у једној великој табели.[10]
Размислите о модификовању Запослени
табеле као у наредном делу:
ЗапослениИД | Презиме | Држава | ОдељењеИД |
---|---|---|---|
123 | Раферти | Аустралија | 31 |
124 | Џоунс | Аустралија | 33 |
145 | Хаизенберг | Аустралија | 33 |
201 | Робинсон | Сиједињене Државе | 34 |
305 | Смит | Немачка | 34 |
306 | Вилиамс | Немачка | NULL |
Пример решења упита може бити као у наставку:
SELECT F.ЗапослениИД, F.Презиме, S.ЗапослениИД, S.Презиме, F.Држава
FROM Запослени F INNER JOIN Запослени S ON F.Држава = S.Држава
WHERE F.ЗапослениИД < S.ЗапослениИД
ORDER BY F.ЗапослениИД, S.ЗапослениИД;
Чији резултат се генерише наредном табелом.
ЗапослениИД | Презиме | ЗапослениИД | Презиме | Држава |
---|---|---|---|---|
123 | Раферти | 124 | Џоунс | Аустралија |
123 | Раферти | 145 | Хаизенберг | Аустралија |
124 | Џоунс | 145 | Хаизенберг | Аустралија |
305 | Смит | 306 | Вилиамс | Немачка |
За овај пример:
F
иS
су псеудоними за прву и другу копију табеле запослених.- Услов
F.Држава = S.Држава
искључује упаривање између запослених из супротних држава. Задато питање жели парове запослених из исте државе. - Услов
F.ЗапослениИД < S.ЗапослениИД
искључује упаривање где јеЗапослениИД
од првог запосленог већи или једнакЗапослениИД
са другим запосленим. Другим речима, ефекат овог услова је да искључи дупло упаривање и самоупаривање. Без тога, следећа мање корисна табела била би генерисана (тебла испод прикзује само "Немачка" део резултата):
ЗапослениИД | Презиме | ЗапослениИД | Презиме | Држава |
---|---|---|---|---|
305 | Смит | 305 | Смит | Немачка |
305 | Смит | 306 | Вилиамс | Немачка |
306 | Вилиамс | 305 | Смит | Немачка |
306 | Вилиамс | 306 | Вилиамс | Немачка |
Само једно од два средња упарења су довољна да задовоље питање, и скроз горња и скроз доња су непотребна за овај пример.
Алтернативе
[уреди | уреди извор]Ефекат спољашњег придруживања може се добити коришћењем UNION ALL између INNER JOIN и SELECT од редова у "главној" табели који не употпуњују услове придруживања. На пример,
SELECT запослени.Презиме, запослени.ОдељењеИД, одељење.ОдељењеНазив
FROM запослени
LEFT OUTER JOIN одељење ON запослени.ОдељењеИД = одељење.ОдељењеИД;
може се такође записати као
SELECT запослени.Презиме, запослени.ОдељењеИД, одељење.ОдељењеНазив
FROM запослени
INNER JOIN одељење ON запослени.ОдељењеИД = одељење.ОдељењеИД
UNION ALL
SELECT запослени.Презиме, запослени.ОдељењеИД, cast(NULL as varchar(20))
FROM запослени
WHERE NOT EXISTS (
SELECT * FROM одељење
WHERE запослени.ОдељењеИД = одељење.ОдељењеИД)
Имплементација
[уреди | уреди извор]Доста посла у систему база података имају за циљ ефикасну имплементацију за придруживање, јер релациони системи обично траже придруживање, али се суочавају са потешкоћама у оптимизацији за ефикасно извршавање. Проблем настаје јер унутрашње повезивање оперишсе са оба Комутативност и Асоцијативност. У пракси, то значи да корисник само снабдева листу табела за придруживање и услове придруживања који се користе, а систем база података има задатак да пронађе најефикаснији начин да изврши операцију. Оптимизација упита одређује како да се изврши упит који садржи придруживање. Оптимизатор упита има две основне слободе:
- Редослед придруживања: Зато што функције спаја коммутативно и асоцијативно, редослед којим систем придружује табеле не мења крајње решење упита. Свакако, редослед придруживања може имати огроман утицај на цену операције придруживања, тако да избор најбољег редпоследа придруживања постаје јако битан.
- Методе придруживања: За дате две табеле и услове придруживања, више Алгоритам могу да произведу резултат придруживања. Који алгоритам ради најефикасније зависи од величине уноса у табели, број редова за сваку табелу који испуњавају услов придруживања, и операција које захтева остатак упита.
Многи алгоритми упоређења третирају свој допринос различито. Може се односити на улазе за придруживање као и "спољашње" и "унутрашње" операције придруживања, или "лево" и "десно", редом. У случају груписаних петљи, на пример, систем база података ће скенирати унос унутрашњих релација за сваки ред спољашње релације.
Један од њих може сврстати план-упита укључујући придруживање као у наставку:[11]
- лево-дубоко
- користи основну табелу (радије него остала придруживања) као унутрашњи операнд за свако придруживање из упита
- десно-дубоко
- користи основну табелу као спољашњи операнд за свако придруживање из упита
- жбунасто
- ни лево-дубоко ни десно-дубоко; оба улаза за придруживање могу резултирати придруживањем
Ова имена су изведена од појаве План упита нацртано као Стабло (структура података), са релацијом спољашњег придруживања на левој и унутрашњег на десној (како налаже конвенција).
Алгоритми придруживања
[уреди | уреди извор]Постоје три основна алгоритма за операције придруживања: Придруживање укрштене петље, Прудруживање сортирање спајањем and Хеш придруживање.
Индекси придруживања
[уреди | уреди извор]Индекси придруживања су Индекси база података који олакшавају обраду упита придружовања у складишту података: они су тренутно (2012) доступни у имплементацијама Orakl[12] и Teradata.[13]
У имплементацији Teradata, наведене колоне, свеобухватна функција за колоне, или компоненте од колоне датума из једне или више табела су наведе коришћењем синтаксе сличне дефиницииј Преглед база података: До 64 колона/колоне израза могу бити наведени у једном индекс придруживању. Опционо, колона која дефинише Примарни кључ композиционог податка може такође да буде наведен: на паралелном хардверу, вредности колоне се користе за поделу садржаја индекса на више дискова. Када се изворне табеле ажурирају интерактивно од стране корисника, садржај индекса придруживања ће бити аутоматски ажурирани. Било који упит чији WHERE клаузула прецизира било коју комбинацију колона или колона израза који је тачно онај подскуп који је дефинисан у индексу придруживања (тзв "прекривени упит") ће довести до индекса придруживања, пре него оригиналне табеле и њихови индекси, да буду консултовани у току извршавања упита.
Oracle имплементације су лимитиране да користе bitmap индексе. bitmap индекси се користе за колоне са малим садржајем (тј, колона које садрже мало више од 300 различитих вредности, у складу са Oracle документацијом): она комбинује колоне са малим садржајем од више повезаних табела. Пример употребе Oracle је у систему инвентар, где различити добављачи обезбеђују различите делове. Шема има три повезане табеле: две "мастер табеле", Део и Добављач, и "табела детаља", Инвентар. Последњи је више и више табела повезивања Добављач за Део, и садржи највише редова. Сваки део садржи и тип дела, и сваки добављач ја основан у САД, и има колону Државе. Не постоји више од 60 држава-територија у САД, и не више од 300 типова делова. Bitmap индекси придруживања је дефинисано употребом стандардног придруживања три-табеле на три горње табеле, и дефинише Део_Тип и Добављач_Држава колоне за индексе. Свакако, то је дефинисано на табели Инвентара, иако су колоное Део_Тип и Добављач_Држава "позајмљене" од Добављач и Део.
Као и за Teradata, Oracle bitmap индекси придруживања се користе да одговоре на упит када WHERE клаузула прецизира колоне ограничене на оне које су укључене у индексу придруживања.
Директно придруживање
[уреди | уреди извор]Неки системи база података дозвољавају кориснику да натера систем да чита табеле у придруживању у одређеном редоследу. Ово се користи када оптимизатор придруживања изабере да чита табеле и неефикасном редоследу. На пример, у MySQL команда STRAIGHT_JOIN
уради унутрашње придруживање али чита табеле тачно у редследу којим су наведене у упиту.[14]
Види још
[уреди | уреди извор]Референце
[уреди | уреди извор]- ^ SQL CROSS JOIN
- ^ In Unicode, the bowtie symbol is ⋈ (U+22C8).
- ^ Greg Robidoux, "Avoid SQL Server functions in the WHERE clause for Performance", MSSQL Tips, 5/3/2007
- ^ Patrick Wolf, "Inside Oracle APEX "Caution when using PL/SQL functions in a SQL statement", 11/30/2006
- ^ Gregory A. Larsen, "T-SQL Best Practices - Don't Use Scalar Value Functions in Column List or WHERE Clauses", 10/29/2009,
- ^ Simplifying Joins with the USING Keyword
- ^ Ask Tom "Oracle support of ANSI joins." Back to basics: inner joins » Eddie Awad's Blog Архивирано на сајту Wayback Machine (19. новембар 2010)
- ^ „Oracle Left Outer Join”. Архивирано из оригинала 07. 10. 2017. г. Приступљено 10. 05. 2016.
- ^ Shah 2005, стр. 165
- ^ Adapted from Pratt 2005, стр. 115–6
- ^ Yu & Meng 1998, стр. 213
- ^ Oracle Bitmap Join Index. URL: http://www.dba-oracle.com/art_builder_bitmap_join_idx.htm
- ^ Teradata Join Indexes. http://www.coffingdw.com/sql/tdsqlutp/join_index.htm Архивирано на сајту Wayback Machine (16. децембар 2012)
- ^ „13.2.9.2 JOIN Syntax”. MySQL 5.7 Reference Manual. Oracle Corporation. Приступљено 03. 12. 2015.
Литература
[уреди | уреди извор]- Pratt, Phillip J (2005), A Guide To SQL, Seventh Edition, Thomson Course Technology, ISBN 978-0-619-21674-0
- Shah, Nilesh (2005) [2002], Database Systems Using Oracle – A Simplified Guide to SQL and PL/SQL Second Edition (International изд.), Pearson Education International, ISBN 978-0-13-191180-2
- Yu, Clement T.; Meng, Weiyi (1998), Principles of Database Query Processing for Advanced Applications, Morgan Kaufmann, ISBN 978-1-55860-434-6, Приступљено 03. 03. 2009