Advertisement
Guest User

5b

a guest
Dec 14th, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
SQL 15.75 KB | None | 0 0
  1. /*-------------------------------------------------------------------------------*/
  2. /*Część II - Pobieranie danych*/
  3. ...
  4.  
  5. /*Odczytywanie danych z wielu tabel*/
  6.  
  7.  
  8.  
  9.  
  10. /*
  11. - Jak za pomocą jednego zapytania odczytać dane z wielu tabel?
  12. - Co to jest złączenie naturalne? Czym różni się złączenie naturalne od nienaturalnego?
  13. - Dlaczego łącząc tabele powinniśmy używać aliasów ich nazw?
  14. */
  15.  
  16.  
  17. /*Złączenia naturalne i nienaturalne*/
  18.  
  19. /*Największy atut relacyjnych baz danych to łączenie odczytywanych tabel, wyników zapytań
  20. i wyników wyrażeń tabelarycznych (podzapytania, widoki oraz funkcje). Jest możliwość
  21. odtwarzania powiązanych ze sobą danych, które uprzednio zostały podzielone między
  22. różne tabele. Można również na różne sposoby te dane łączyć.
  23.  
  24. Następujące zapytanie do tabeli dbo.Zamowienia pozwala poznać identyfikatory zamówień
  25. i realizujących je spedytorów, ale nie można poznać nazw spedytorów.*/
  26.  
  27. /********************************************************************************************************/
  28.       1
  29. /********************************************************************************************************/
  30. SELECT [ID zamowienia], [ID spedytora]
  31. FROM dbo.Zamowienia
  32. WHERE [ID spedytora]=1;
  33.  
  34. /*Wiemy, że kolumna kluczy obcych w jakiejś tabeli przechowuje duplikaty identyfikatorów
  35. wierszy (kluczy podstawowych (głównych)) innej tabeli, dzięki czemu możemy powiązać między
  36. sobą przechowywane w tych tabelach dane. Wartości klucza podstawowego (głównego) muszą być
  37. niepowtarzalne. Natomiast w kolumnie klucza obcego mogą się powtarzać dowolną ilość razy.
  38.  
  39. Klucze obce umożliwiają w ten sposób powiązanie dwóch tabel związkiem (relacją) "jeden do wielu".
  40.  
  41. Powiązanie jest wykonywane poprzez złączenie od strony "wiele" do strony "jeden". Tabela
  42. ze strony "wiele" zawierająca wiersze z kluczem obcym jest złączana krotkowo (przez wykonanie referencji)
  43. z tabelą ze strony "jeden" zawierającą klucz główny - dla identycznych wartości klucza obcego
  44. i głównego. W wyniku otrzymamy tabelę wynikową ze skontaktenowanymi ekstensjami dwóch tabel.
  45.  
  46. Ponieważ identyfikatory spedytorów są zapisane w obu tabelach (w tabeli dbo.Spedytorzy w kolumnie
  47. klucza podstawowego (głównego), a w tabeli dbo.Zamowienia w kolumnie klucza obcego), to możemy ich użyć
  48. do złączenia obu tabel i odczytania numerów zamówień zrealizowanch przez firmę wysyłkową.
  49.  
  50. Złączamy (konkatenujemy) wiersze o równych wartości klucza obcego i głównego.
  51.  
  52. Takie złączenie nazywamy złączeniem naturalnym (ogólnie nazywane złączeniem: klucz obcy-klucz główny.
  53. Akademicka definicja złączenia naturalnego jest inna... To złączenie nazywamy teta-złączeniem.*/
  54.  
  55. /********************************************************************************************************/
  56.       2
  57. /********************************************************************************************************/
  58. SELECT dbo.Zamowienia.[ID zamowienia], dbo.Spedytorzy.Firma --Nazwy kolumn poprzedzone nazwami tabel.
  59.                                                             --Zapobiega to błędom. Aliasy będą omówione dalej.
  60. FROM dbo.Spedytorzy JOIN dbo.Zamowienia                     --Nazwy odczytywanych (złączanych) tabel.
  61. ON dbo.Zamowienia.[ID spedytora] = dbo.Spedytorzy.ID        --Warunki łączenia tabel. Do wyniku zapytania
  62. WHERE dbo.Spedytorzy.Firma='Firma wysylkowa A';             --trafią tylko te wiersze z obu tabel, dla
  63.                                                             --których kolumny [ID spedytora] są takie jak
  64.                                                             --wartości kolumny ID.
  65.                                                             --Wygenerowanie wszystkich możliwych kombinacji
  66.                                                             --łączonych tabel, a następnie usunięcie z tak otrzymanego
  67.                                                             --wierszy zbioru pośredniego, wierszy niespełniających
  68.                                                             --warunku złączenia.
  69.            
  70. /*UWAGA: W ekstensji tabel złączanych nie ma krotek osieroconych. DLATEGO pozycje tabel (operandów) operatora JOIN
  71. można zamienić i otrzymane wyniki zapytania nie zmienią się. Innym powodem takiej możliwości jest wpływ
  72. optymalizatora algebraicznego DBMSu na analizę leksykalną zapytań i generowanie poprawnego (choć nie zawsze) kodu
  73. algebraicznego do wykonywania zapytań. Zamiana pozycyjna tabel NIE JEST ZATEM ZALECANA (czasami występują błędy
  74. logiczne w tak zapisanych złączeniach) i znacznie utrudnia to ich wykrywanie.*/
  75.  
  76. /*Operator JOIN ... ON można zastąpić warunkiem WHERE:*/
  77.  
  78. SELECT dbo.Zamowienia.[ID zamowienia], dbo.Spedytorzy.Firma --Można złączać bez użycia operatora JOIN                                                 
  79. FROM dbo.Spedytorzy, dbo.Zamowienia                         --i słowa kluczowego ON, stosując klauzulę WHERE
  80.                                                             --z (odpowiednim) warunkiem selekcji krotek złączanych.
  81.                                                             --Silnik DBMS wie, że ma złączać od strony jeden do wiele.
  82. WHERE dbo.Zamowienia.[ID spedytora] = dbo.Spedytorzy.ID AND dbo.Spedytorzy.Firma='Firma wysylkowa A';
  83.  
  84.  
  85.  
  86. SELECT dbo.Zamowienia.[ID zamowienia], dbo.Spedytorzy.Firma --Nazwy kolumn poprzedzone nazwami tabel.
  87.                                                             --Zapobiega to błędom. Aliasy będą omówione dalej.
  88. FROM dbo.Spedytorzy JOIN dbo.Zamowienia                     --Nazwy odczytywanych (złączanych) tabel
  89. ON dbo.Zamowienia.[ID spedytora] = dbo.Spedytorzy.ID        
  90. WHERE dbo.Spedytorzy.Firma='Firma wysylkowa A';            
  91.  
  92. /********************************************************************************************************/
  93.       3
  94. /********************************************************************************************************/
  95. SELECT dbo.Zamowienia.[ID zamowienia], dbo.Spedytorzy.Firma
  96. FROM dbo.Zamowienia, dbo.Spedytorzy
  97. WHERE dbo.Zamowienia.[ID spedytora] = dbo.Spedytorzy.ID
  98. AND dbo.Spedytorzy.Firma = 'Firma wysylkowa B'; --WHERE jest wykonywane po FROM. Warunki te (złączenia i wyboru)
  99.                                                 --nie powinny być stosowane zamiennie (tu w celu filtrowania raz
  100.                                                 --po firmie Firma wysyłkowa A, a innym razem po firmie
  101.                                                 --Firma wysyłkowa B - co jest "zmieszaniem" złączania i filtrowania
  102.                                                 --wynikow).
  103.                                                 --Lepiej zatem używać jawnie JOIN ... ON.
  104.                                                 --Zatem zastępowanie złączeniowego operatora JOIN ... ON warunkiem
  105.                                                 --WHERE nie jest zalecane.
  106. /*
  107. Klauzula WHERE jest wykonywana po klauzuli FROM, a więc możemy w niej wyeliminować dowolne, zwracane przez
  108. klauzulę FROM wiersze, ale operacja odwrotna jest niemożliwa. Dlatego warunki złączenia i wyboru nie powinny
  109. być stosowane zamiennie.
  110.  
  111. Zastępowanie złączania filtrowaniem ma kilka zasadniczych wad:
  112.  
  113. 1. Jest niezgodne ze standardem SQL.
  114. 2. Pogarsza czytelność zapytań, szczególnie tych z rozbudowaną klauzulą WHERE.
  115. 3. W złączeniach zewnętrznych (omówimy je później) może być przyczyną trudnych do wykrycia błędów logicznych.
  116.  
  117.  
  118. "Naturalny" związek między danymi...
  119.  
  120. Dane klienta (zapisane w tabeli dbo.Klienci), który złożył zamówienie o podanym numerze (zapisanym w tabeli
  121. dbo.Zamówienia):
  122. */
  123. /********************************************************************************************************/
  124.       4
  125. /********************************************************************************************************/
  126. SELECT Firma
  127. FROM dbo.Klienci JOIN dbo.Zamowienia
  128. ON dbo.Klienci.ID = dbo.Zamowienia.[ID klienta]
  129. WHERE [ID zamowienia]=31;
  130.  
  131.  
  132. /*
  133. DYGRESJA (dla bardziej zaawansowanych): Serwer SQL 11 (i wersje wyższe) nie obsługuje stadardowego operatora NATURAL JOIN.
  134. Nie obsługuje też skróconego JOIN ... USING (kolumna) spotykanych w innych dialektach SQL. Zamiast raz podać nazwę kolumny
  135. występującej w obu tabelach, trzeba w klauzuli ON dwukrotnie ją powtórzyć. Nie stosuje się tu tzw. kompatybilności
  136. typów kolumn...
  137.  
  138.  
  139.  
  140. Język SQL pozwala też na wykonywanie złączeń na podstawie wartości niekluczowych.
  141.  
  142. Ponieważ wynik takiego złączenia nie odzwierciedla naturalnego połączenia danych,
  143. takie złączenie nazywa się złączeniem nienaturalnym (ale nazwa akademicka to: złączenie naturalne...! vide wykład).
  144.  
  145.  
  146.  
  147. Im bardziej znormalizowana baza danych, tym mniej zawiera duplikatów danych i tym rzadziej używane są
  148. w niej złączenia nienaturalne. W bazie Northwind_bezplzn, w tabelach dbo.Klienci i dbo.Pracownicy, są
  149. zapisane nazwiska (odpowiednio klientów i pracowników, oraz nazwy miast, w ktorych mieszkają. Zatem można
  150. złączyć obie te tabele w nienaturalny sposób, na podstawie nazw miast. Wynikiem takiego złączenia jest
  151. lista nazwisk klientów i pracowników mieszkających w tych samych miastach.
  152. */
  153.  
  154. /*Lista nazwisk klientów i pracowników mieszkających w tych samych miastach;
  155. */
  156. /********************************************************************************************************/
  157.       5
  158. /********************************************************************************************************/
  159. SELECT dbo.Klienci.Nazwisko, dbo.Pracownicy.Nazwisko,
  160. dbo.Klienci.Miasto, dbo.Pracownicy.Miasto
  161. FROM dbo.Klienci JOIN dbo.Pracownicy
  162. ON dbo.Klienci.Miasto = dbo.Pracownicy.Miasto; --Analiza: W bazach relacyjnych do łączenia tabel należy
  163.                                                --używać kluczy. Złączenia nienaturalne odwołujące się do
  164.                                                --kolumn, które mogą zawierać powtarzające się wartości,
  165.                                                --są niejednoznaczne. Na przykład, krotki dla nazwisk
  166.                                                --Obwarzanek, Ciesielska, Bochenek, Radzikowska są
  167.                                                --kilkakrotnie powtórzone.
  168.  
  169. /*Żeby się o tym upewnić, wystarczy dodać do wyniku poprzedniego zapytania identyfikatory pracowników i
  170. klientów:*/
  171.  
  172. /********************************************************************************************************/
  173.       6
  174. /********************************************************************************************************/
  175. SELECT dbo.Klienci.ID, Klienci.Nazwisko, dbo.Pracownicy.ID, dbo.Pracownicy.Nazwisko,
  176. dbo.Klienci.Miasto, dbo.Pracownicy.Miasto
  177. FROM dbo.Klienci JOIN dbo.Pracownicy
  178. ON dbo.Klienci.Miasto = dbo.Pracownicy.Miasto;
  179.  
  180. /*Ponieważ dwóch klientów i jeden pracownik mieszka w Gdańsku, dane pracownika z Gdańska musiały być powtórzone.
  181. Jest też sporo innych powtórzeń, bo dwóch klientów i czterech pracowników mieszka w Pruszkowie. Dane klienta
  182. z Pruszkowa zostały powtórzone czterokrotnie, a dane pracowników z Gdańska dwukrotnie.*/
  183.  
  184.  
  185.  
  186. /*Aliasy*/
  187.  
  188. /*
  189. Nie stosujemy, jeśli zapytanie odwołuje się tylko do jednej tabeli, poprzedzanie nazw kolumn nazwą tabeli jest
  190. niepotrzebne (nazwy kolumn są jednoznaczne).
  191. Gdy zapytanie odwołuje się do wielu tabel, to nazwy kolumn mogą występować w różnych tabelach i serwer bazodanowy
  192. nie jest w stanie tylko na podstawie nazw określić, do której kolumny chcieliśmy się odwołać:
  193. */
  194.  
  195. /********************************************************************************************************/
  196.       7
  197. /********************************************************************************************************/
  198. SELECT ID                                                   --Zapytanie błędne. Wielznaczność nazwy kolumny ID.
  199. FROM dbo.Produkty JOIN dbo.[Szczegoly zamowienia zakupu]    --Ambiguous column name 'ID'.
  200. ON dbo.Produkty.[ID dostawcow]= dbo.[Szczegoly zamowienia zakupu].[ID produktu];
  201.  
  202. /*Za pomocą aliasów można polepszyć czytelność zapytań z długimi nazwami tabel, czasami także wobec wielokrotnych
  203. wystąpień tych nazw w zapytaniu. Powinniśmy im nadać aliasy a potem tych aliasów konsekwentnie używać w całym
  204. zapytaniu.*/
  205.  
  206. /********************************************************************************************************/
  207.       8
  208. /********************************************************************************************************/
  209. SELECT P.ID
  210. FROM dbo.Produkty AS P JOIN dbo.[Szczegoly zamowienia zakupu] AS S
  211. ON P.ID = S.[ID produktu];
  212.  
  213. /*Stosując aliasy unikamy też trudnych do wykrycia błędów wynikających ze sposobu sprawdzania nazw obiektów przez
  214. serwer. Gdybyśmy się pomylili wpisując nazwę kolumny, a w którejś ze złączanych tabel istniałaby kolumna
  215. o wprowadzonej przez nas nazwie, serwer nie zgłosiłby błędu, tylko odczytałby dane z innej kolumny, niż chcieliśmy.*/
  216.  
  217.  
  218. /*Złączenia równościowe i nierównościowe*/
  219. /********************************************************************************************************/
  220.       9
  221. /********************************************************************************************************/
  222. SELECT Z.[ID zamowienia], SZ.[ID produktu], SZ.[ID zamowienia]
  223. FROM dbo.Zamowienia AS Z JOIN dbo.[Szczegoly zamowien] AS SZ
  224. ON Z.[ID zamowienia] = SZ.[ID produktu]; --Od razu widać po wyniku, że jest to wynik niepożądany (niepoprawny).
  225. --                     xxxxxxxxxxxxxxxx  --Powód: wartości kluczy podstawowych z reguły są takie same, co wykazuje
  226.                                          --to złączenie równościowe. Ale przecież chodziło o złączenie równościowe
  227.                                          --klucz obcy - klucz podstawowy, co widać w zapytaniu poprawnym poniżej...,
  228.                                          --również w wynikach zapytania.
  229. /********************************************************************************************************/
  230.       10
  231. /********************************************************************************************************/
  232. SELECT Z.[ID zamowienia], SZ.[ID produktu], SZ.[ID zamowienia]
  233. FROM dbo.Zamowienia AS Z JOIN dbo.[Szczegoly zamowien] AS SZ
  234. ON Z.[ID zamowienia] = SZ.[ID zamowienia];                                      
  235. --                     xxxxxxxxxxxxxxxxxx
  236.  
  237. /*Warunki złączeń mogą być inne niż równościowe. Wtedy stosujemy inne operatory relacyjne.*/
  238. /********************************************************************************************************/
  239.       11
  240. /********************************************************************************************************/
  241. SELECT P.[Kod produktu], P.[Cena katalogowa], SZ.[Cena jednostkowa]
  242. FROM dbo.Produkty AS P JOIN dbo.[Szczegoly zamowien] AS SZ
  243. ON P.[Cena katalogowa] > SZ.[Cena jednostkowa];
  244.  
  245. /*Intencją zapytania było sprawdzenie, które ceny dla konsumenta mają narzut.
  246.  
  247. Po wynikach złączeń z powyższego zapytania widać, że zawierają one mmnóstwo powtórzonych wierszy. Jednym
  248. z nielicznych zastosowań tych złączeń jest analiza danych polegająca na wyszukiwaniu istniejących między tymi danymi
  249. zależności. Złączenia nierównościowe z reguły występują razem ze złączeniami naturalnymi - jak w następującym
  250. zapytaniu:*/
  251. /********************************************************************************************************/
  252.       12
  253. /********************************************************************************************************/
  254. SELECT P.[Kod produktu], P.[Cena katalogowa], SZ.[Cena jednostkowa]
  255. FROM dbo.Produkty AS P JOIN dbo.[Szczegoly zamowien] AS SZ
  256. ON P.[Cena katalogowa] >= SZ.[Cena jednostkowa] AND P.ID =SZ.[ID produktu];
  257.  
  258. --Widzimy, że wszystkie ceny dla konsumenta mają narzut (choć mogłyby go nie mieć)...
  259.  
  260. --UWAGA: Cena katalogowa (hurtowa) jest zwykle większa (o narzut) od ceny jednostkowej (detalicznej, dla konsumenta).
  261.  
  262. /*Złączenia zewnętrzne OUTER.*/
  263.  
  264. /*-------------------------------------------------------------------------------*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement