Połączenia krzyżowe Złączenie typu CROSS JOIN Złączenie CROSS JOIN jest to tzw. złączenie krzyżowe, którego ogólna postać wygląda następująco: SELECT kolumna1, kolumna2,..., kolumnan FROM tabela1 CROSS JOIN tabela2 gdzie N oznacza ostatnią kolumnę tabeli. Wykonuje ono iloczyn kartezjański na podstawie łączonych tabel, inaczej mówiąc łączy każdy wiersz tabeli tabela1 z każdym wierszem tabeli tabela2. Jest ona odpowiednikiem znanej instrukcji: SELECT kolumna1, kolumna2,...,kolumnan FROM tabela1, tabela2 przykład SELECT d.id_dzialu, p.p_id FROM dzialy d CROSS JOIN projekty p; SELECT d.id_dzialu, p.p_id FROM dzialy d, projekty p; --IOCZYN KARTEZJAŃSKI, CROSS JOIN 616 WYNIKÓW SELECT C.CategoryName, p.productname FROM Categories C CROSS JOIN Products p; SELECT C.CategoryName, p.productname FROM Categories C,Products p; -- ACZENIE TABEL 77 WYNIKÓW SELECT Categories.CategoryName, Products.ProductName FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID Połączenia wielokrotne W rzeczywistych środowiskach bazodanowych, kwerendy dotyczą zazwyczaj łączenia wielu tabel. str. 1
Dla przykładu rozważmy scenariusz zapytania SQL w bazie testowej Northwind. Interesują nas informacje o Klientach z określonego miasta Madrytu. Chcemy znać detale ich zamówień, złożonych we wrześniu 1996 nazwy i ilości produktów, które kupili. Przykładowa kwerenda: SELECT c.companyname, o.orderid, od.quantity, p.productname FROM dbo.customers c LEFT OUTER JOIN dbo.orders o on c.customerid = o.customerid INNER JOIN dbo.[order Details] od on od.orderid = o.orderid INNER JOIN dbo.products p on od.productid = p.productid WHERE c.city = 'Madrid' AND o.orderdate BETWEEN '1996-09-01' AND '1996-09-3 0' Zasady połączeń, obowiązujące w zapytaniach do wielu tabel SQL, są identyczne jak te opisane dla przykładu łączenia dwóch tabel. Zaczynamy zawsze od łączenia dwóch pierwszych, stojących zaraz po FROM. Możemy także stosować nawiasy (o tym w następnym przykładzie). Mają one priorytet czyli łączona jest tabela z wynikiem operacji w nawiasach. Przy łączeniu trzech i więcej tabel, każda kolejna jest dołączana do wyniku poprzedniego kroku. Algorytm działa iteracyjnie od lewej do prawej, aż do przetworzenia ostatniego zbioru. Więcej info na http://www.sqlpedia.pl/logiczne-przetwarzanie-zapytan-sql-laczenie-wielu-tabel/ str. 2
Złączenie tabeli z nią samą Złączenie typu Self JOIN O złączeniu Self JOIN mówimy, gdy po lewej i prawej stronie złączenia występuje ta sama tabela. W tym typie złączeń za niezbędne uważa się użycie aliasów. SELECT d1.nazwa, d2.nazwa FROM dzialy d1 JOIN dzialy d2 USING (adres) WHERE d1.nazwa!= d2.nazwa; SELECT d1.nazwa, d2.nazwa FROM dzialy d1, dzialy d2 WHERE d1.adres = d2.adres AND d1.nazwa!= d2.nazwa; Ostatnia linijka w kodzie zapobiega wyświetlaniu wierszy, w których w obu kolumnach będzie to samo (sensem kodu jest wyświetlanie par tych oddziałów, co mają ten sam adres) SELF JOIN połączenie tabeli z samą sobą Język SQL jest elastyczny i jeśli coś jest zbiorem, może być użyte we FROM wiele razy. Połączenia typu SELF JOIN to zawsze jedno z już poznanych INNER, CROSS lub OUTER JOIN, w T-SQL nie stosuje się zapisu SELF JOIN. select * from Employees SELECT e1.lastname+ ' ' + e1.firstname as Pracownik, e1.title, e2.lastname + ' ' + e2.firstname as Manager, e2.title as ManStanowisko FROM Employees e1 LEFT OUTER JOIN Employees e2 on e1.employeeid=e2.reportsto Ten przykład bazuje na istniejącej relacji, kluczu obcym tabeli Employees do samej siebie, jednak wcale nie musi ta referencja być jawnie i permanentnie określona. Wszystkie do tej pory prezentowane przykłady, łączyły tabele w naturalny sposób ich powiązań. Po kolumnach będącymi jednocześnie kluczami obcymi/podstawowymi tabel. Ogólną zasadą łączenia jest możliwość jej realizacji po dowolnych kolumnach. Musi być spełniony tylko jeden warunek kompatybilność typów danych łączonych atrybutów. To jak zapiszemy warunek i czy będzie miał sens, zależy tylko od nas język SQL nie ogranicza tu naszej wyobraźni. Dodatkowo, na wartościach atrybutów po których łączymy, możemy wykonywać dowolne operacje. Przetwarzać je za pomocą funkcji skalarnych, wykonywać działania arytmetyczne, łączenia stringów etc str. 3
Operatory zapytań wewnętrznych EXIST,ANY, SOME, ALL 1 Rezultat zwracany przez podzapytanie (zapytanie wewnętrzne) można porównywać za pomocą jednego specjalnych operatorów dostępnych w SQL: EXISTS, ANY, SOME lub ALL. Możemy za ich pomocą sprawdzić między innymi czy podzapytanie zwróciło jakieś dane lub wartość wiersza. EXISTS zwraca true jeśli podzapytanie zwróciło jakiekolwiek dane, jeśli nie zwraca false, ANY sprawdza wartość dowolnego wiersza zwróconego przez podzapytanie, SOME sprawdza wartość dowolnego wiersza zwróconego przez podzapytanie (ten operator działa tak samo jak ANY), ALL sprawdza wartości wszystkich wierszy zwróconych przez podzapytanie. PracownicyI D ( ) Do ćwiczeń będziemy wykorzystywać bazę danych zbudowaną z dwóch tabel: Tabela: pracownicy Miast o ( ) Imie Nazwisko Data_urodzeni a Stanowisk o Data_zatrudnieni a 1 1 Jan Kowalski 1984-12-23 Programista 1999-12-09 2 1 Adam Adamiak 1991-08-08 Menadżer 2011-31-01 3 3 Jakub Wawrzynia k 1990-16-03 Programista 2010-01-04 4 2 Micha ł Gdzie kluczem ( ) jest kolumna PracownicyID. Tabela: miastozamieszkania MiastoZamieszkaniaID ( ) Miasto 1 Kraków 2 Warszawa 3 Wrocław 4 Londyn Jakubiak 1981-05-02 Projektant 1998-09-22 Gdzie kluczem ( ) jest kolumna MiastoZamieszkaniaID oraz ( ). Obie tabele zostały połączone za pomocą relacji PracownicyID -> MiastoZamieszkaniaID ( -> ). Oznacza to, że do każdego pracownika zostało przypisane jego miasto zamieszkania. Ćwiczenia Exists Pobierzmy z bazy danych informacje o miastach, w których nie mieszkają żadni pracownicy: SELECT Miasto FROM miastozamieszkania AS mz WHERE 1 http://strefakodera.pl/bazy-danych/sql/podzapytania-operatory-exists-any-some-all-w-sql-cz-v/2 str. 4
NOT EXISTS (SELECT * FROM pracownicy WHERE mz.miastozamieszkaniaid = miasto); Rezultat: Miasto Londyn Oczywiście w tym ćwiczeniu musieliśmy użyć przeczenia (NOT), NOT EXISTS jest prawdziwe (zwraca true) jeśli nie zostanie zwrócony przez podzapytanie żaden rekord, a właśnie o to nam chodziło w tej kwerendzie. Informacje o pracownikach nie mieszkających w Krakowie: SELECT imie, nazwisko FROM pracownicy WHERE EXISTS (SELECT * FROM miastozamieszkania WHERE pracownicy.miasto = miastozamieszkaniaid AND miasto <> 'Kraków') Rezultat: Imie Nazwisko Jakub Wawrzyniak Michał Jakubiak ANY, SOME UWAGA: Omawiany materiał działa na bazach danych firmy Microsoft. Operator ANY/SOME jest prawdziwy (zwraca true) jeśli którekolwiek ze zwróconych przez podzapytanie danych spełni poprzedzający go warunek logiczny. Jak pisałem na wstępie operator ten sprawdza wszystkie rekordy. SELECT imie, nazwisko FROM pracownicy WHERE 'Madryt' <> ANY (SELECT miasto FROM miastozamieszkania); ezultat: Imię Nazwisko Jan Kowalski Adam Adamiak Jakub Wawrzyniak Michał Jakubiak str. 5
Oczywiście ANY możemy zastąpić operatorem SOME. ALL UWAGA: Omawiany materiał działa na bazach danych firmy Microsoft. Operator ALL działa w zasadzie tak samo jak ANY/SOME z tym wyjątkiem, że sprawdza wszystkie dane. Wszystkie zwrócone przez podzapytanie rekordy muszą spełniać podany wcześniej warunek logiczny. SELECT imie, nazwisko FROM pracownicy WHERE 'Londyn' <> ALL (SELECT miasto FROM miastozamieszkania); Rezultat: Nie otrzymamy żadnego wyniku. 0 rekordów. W tabeli miastozamieszkania znajduje się miasto Londyn dlatego warunek logiczny nie został spełniony. Usuwanie danych z bazy danych w SQL Kasowanie informacji zdezaktualizowanych w bazie danych wykonujemy za pomocą zapytania DELETE. Instrukcja ta służy do kasowania wybranych wierszy z danej tabeli, jeżeli potrzebujemy na przykład wyczyścić całą tabelę to możemy zastosować instrukcję TRUNCATE TABLE. Kasowanie wybranych rekordów Ogólna składnia zapytania DELETE: DELETE FROM nazwatabeli WHERE waruneklogiczny; Przykład: DELETE FROM tab1 WHERE id = '1'; Usuwanie całej zawartości Kasowanie rekordu po rekordzie przy milionie pozycji może być nieco męczące. Twórcy SQL pomyśleli również i o tym aspekcie dodając instrukcję TRUNCATE TABLE. Ogólna składnia: TRUNCATE TABLE nazwatabeli; str. 6