SQL - notatki z wykładu część czwarta PDF

Title SQL - notatki z wykładu część czwarta
Course Wstęp do programowania
Institution Wyższa Szkoła Biznesu – National-Louis University
Pages 17
File Size 345.2 KB
File Type PDF
Total Downloads 577
Total Views 732

Summary

dr H. TelegaJęzyk SQL, część 4.1. Podzapytania - podstawy.Podzapytanie to zdanie SELECT umieszczone w środku innego zdania SQL (zdania SELECT lubinnego). Podzapytanie może być umieszczone w klauzulach SELECT, FROM, WHERE, HAVING,ORDER BY (chociaż w tym ostatnim przypadku rzadko ma to sens).Podzapyta...


Description

Język SQL, cz.4. dr H. Telega

Język SQL, część 4. 1. Podzapytania - podstawy. Podzapytanie to zdanie SELECT umieszczone w środku innego zdania SQL (zdania SELECT lub innego). Podzapytanie może być umieszczone w klauzulach SELECT, FROM, WHERE, HAVING, ORDER BY (chociaż w tym ostatnim przypadku rzadko ma to sens). Podzapytania w klauzuli SELECT. --Dla każdego produktu wypisać średnią cenę produktu, wyliczoną dla całej tabeli. --W kolumnie ma być we wszystkich wierszach jednakowa wartość. SELECT ProductID, ProductName, CategoryID, UnitPrice FROM Products SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products) AS Srednia FROM Products

Podzapytania w klauzuli WHERE. --Wypisać dane tylko tych produktów, których cena jest większa od średniej --ceny wyliczonej w całej tabeli --To jest źle (na etapie realizacji klauzuli WHERE średnia nie jest jeszcze --policzona): SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products) AS Srednia FROM Products WHERE UnitPrice > Srednia --Rozwiązanie poprawne: SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products) AS Srednia FROM Products WHERE UnitPrice > (SELECT AVG(UnitPrice) FROM Products) --Sama średnia nie musi być wypisywana, żeby można ją było użyć w klauzuli WHERE SELECT ProductID, ProductName, CategoryID, UnitPrice FROM Products WHERE UnitPrice > (SELECT AVG(UnitPrice) FROM Products) --To jest źle - podzapytanie zwraca więcej niż jedna wartość, a w tym miejscu system --oczekuje pojedynczej wartości: SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products GROUP BY CategoryID) AS Srednia FROM Products

Podzapytania w klauzuli FROM. SELECT ProductID, UnitPrice FROM (SELECT ProductID, ProductName, UnitPrice FROM Products) AS TMP

--Przypomnienie rozwiązywanego już wcześniej zadania: --Dla każdego klienta (wystarczy CustomerID) należy podać --sumę kwot na wszystkich jego zamówieniach

Język SQL, cz.4. dr H. Telega

--Dwie kolumny: CustomerID, Sum SELECT * FROM Orders SELECT * FROM [Order Details] --Rozwiązanie: SELECT O.CustomerID, SUM(ROUND(UnitPrice*Quantity*CAST((1-Discount) AS MONEY),2))AS Total FROM [Order Details] OD JOIN Orders O ON OD.OrderID=O.OrderID GROUP BY CustomerID ORDER BY Total DESC --Do powyższego rozwiązania należy dodać liczbę zamówień --To jest ZŁE rozwiązanie. Wypisze dla każdego klienta --liczbę szczegółowych pozycji zamiast liczbę zamówień: SELECT O.CustomerID, SUM(ROUND(UnitPrice*Quantity*CAST((1-Discount) AS MONEY),2))AS Total, COUNT(*) AS NumberOfOrders FROM [Order Details] OD JOIN Orders O ON OD.OrderID=O.OrderID GROUP BY CustomerID ORDER BY Total DESC --Ile było zamówień dla każdego odbiorcy? SELECT CustomerID, COUNT(*) NumberOfOrders FROM orders GROUP BY CustomerID --Można wykorzystać COUNT(DISTINCT) SELECT O.CustomerID, SUM(ROUND(UnitPrice * Quantity * CAST((1-Discount) AS MONEY),2)) AS Total, COUNT(DISTINCT OD.OrderID) AS NumberOfOrders FROM [Order Details] OD JOIN Orders O ON OD.OrderID=O.OrderID GROUP BY CustomerID ORDER BY Total DESC

--Gdyby w systemie baz danych, z którego korzystamy, nie było konstrukcji --COUNT(DISTINCT …) można byłoby posłużyć się podzapytaniami --złączonymi w klauzuli FROM SELECT * FROM ( SELECT CustomerID, COUNT(*) NumberOfOrders FROM orders GROUP BY CustomerID ) AS Subquery1 JOIN ( SELECT O.CustomerID, SUM(ROUND(UnitPrice*Quantity*CAST((1-Discount) AS MONEY),2))AS TotalAmount FROM [Order Details] OD JOIN Orders O ON OD.OrderID=O.OrderID GROUP BY CustomerID ) AS Subquery2 ON Subquery1.CustomerID = Subquery2.CustomerID ORDER BY TotalAmount DESC

--Jak do powyższego zestawu dodać nazwę klienta? --Rozwiązanie: SELECT Subquery1.*,Subquery2.Amount, C.CompanyName FROM

Język SQL, cz.4. dr H. Telega

( SELECT CustomerID, COUNT(*) NumberOfOrders FROM orders GROUP BY CustomerID) AS Subquery1 JOIN ( SELECT O.CustomerID, SUM(ROUND(UnitPrice*Quantity*CAST((1-Discount) AS MONEY),2))AS TotalAmount FROM [Order Details] OD JOIN Orders O ON OD.OrderID=O.OrderID GROUP BY CustomerID ) AS Subquery2 ON Subquery1.CustomerID = Subquery2.CustomerID JOIN Customers AS C ON Subquery1.CustomerID=C.CustomerID --Wypisać dla każdej kategorii jej identyfikator, nazwę --oraz liczbę produktów w tej kategorii i średnią --cenę w tej kategorii SELECT CategoryID, AVG(UnitPrice) AS AveragePrice, COUNT(*) AS NumberOfProducts FROM Products GROUP BY CAtegoryID SELECT * FROM Products SELECT * FROM Categories SELECT P.*, CategoryName FROM ( SELECT CategoryID, AVG(UnitPrice) AS AveragePrice, COUNT(*) AS NumberOfProducts FROM Products GROUP BY CategoryID ) AS P JOIN Categories C ON P.CategoryID = C.CategoryID

2. Podzapytanie skorelowane (zależne od zapytania głównego). --Dla każdego produktu wypisać jaka jest średnia cena --produktów w kategorii, do której produkt należy SELECT ProductID, ProductName, CategoryID, UnitPrice FROM Products SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS AveragePriceInTable FROM Products AS P1 --Wypisać wszystkie produkty, których cena jednostkowa --jest większa od średniej ceny wyliczonej w kategorii, --do której produkt należy. SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS AveragePriceInTable FROM Products AS P1 WHERE UnitPrice > (SELECT AVG(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID)

Język SQL, cz.4. dr H. Telega

3. Operatory CROSS APPLY i OUTER APPLY. Wyżej przedstawiony sposób korelowania zapytania głównego i podzapytania może być zastosowany tylko, jeśli jest między nimi relacja główny – podrzędny. Nie można analogicznej konstrukcji zastosować na przykład, jeśli chcielibyśmy złączyć operatorem JOIN w klauzuli FROM dwa źródła danych, przy czym chcielibyśmy przy wyznaczaniu rekordów w jednym źródle danych odwoływać się do danych z drugiego źródła. Źródła te są w pewnym sensie równorzędne i nie można zastosować wcześniej przedstawionej metody korelacji zapytań. W takim przypadku przydaje się operator CROSS APPLY lub OUTER APPLY. Ich działanie można prześledzić na następującym przykładzie. Chcemy dla każdego klienta wyświetlić jego identyfokator i nazwę oraz identyfikatory i daty jego trzech najnowszych zamówień. Nie można tego wykonać w ten sposób: SELECT C.CustomerID, CompanyName, Subquery.OrderID, Subquery.OrderDate FROM Customers AS C JOIN (SELECT TOP 3 OrderID, OrderDate, CustomerID FROM Orders AS O WHERE O.CustomerID = C.CustomerID ORDER BY OrderDate DESC) AS Subquery ON C.CustomerID = Subquery.CustomerID ORDER BY CustomerID, Subquery.OrderDate DESC

Powodem jest to, że próbujemy skorelować podzapytanie w klauzuli FROM z tabelą. Nie można tego robić, obydwa te źródła danych łac zone operatorem JOIN są w pewnym sensie równorzędne. Z pomocą przychodzi operator CROSS APPLY, który dla każdego rekordu z tabeli Customers wykona podzapytanie i połączy każdy rekord z Customers z wszystkimi rekordami, które zostaną wybrane przez wywołane (skorelowane) podzapytanie. SELECT CustomerID, CompanyName, Subquery.OrderID, Subquery.OrderDate FROM Customers AS C CROSS APPLY ( SELECT TOP 3 OrderID, OrderDate FROM Orders AS O WHERE O.CustomerID = C.CustomerID ORDER BY OrderDate DESC ) AS Subquery ORDER BY CustomerID, Subquery.OrderDate DESC

Można zamienić wersję TOP 3 na TOP 3 WITH TIES: SELECT CustomerID, CompanyName, Subquery.OrderID, Subquery.OrderDate FROM Customers AS C CROSS APPLY ( SELECT TOP 3 WITH TIES OrderID, OrderDate FROM Orders AS O WHERE O.CustomerID = C.CustomerID ORDER BY OrderDate DESC ) AS Subquery ORDER BY CustomerID, Subquery.OrderDate DESC

Powyższe konstrukcje, wykorzystujące operator CROSS APPLY nie wyświetlają danych tych klientów, dla których skorelowane podzapytanie nie wybierze żadnego rekordu.

Język SQL, cz.4. dr H. Telega

Operator OUTER APPLY spowoduje wyświetlenie danych również tych klientów, którzy nic jeszcze nie zamówili: SELECT CustomerID, CompanyName, Subquery.OrderID, Subquery.OrderDate FROM Customers AS C OUTER APPLY ( SELECT TOP 3 OrderID, OrderDate FROM Orders AS O WHERE O.CustomerID = C.CustomerID ORDER BY OrderDate DESC ) AS Subquery ORDER BY CustomerID, Subquery.OrderDate DESC

W zestawie wynikowym będziemy mieć dwa rekordy więcej – klienci o identyfikatorach FISSA i PARIS jeszcze nic nie zamówili.

4. Zamiana podzapytania na złączenie tabel. Podzapytania umieszczone między SELECT i FROM lub w klauzuli WHERE mogą być zamienione na złączenie z odpowiednio zapisanym podzapytaniem. --Dla każdego produktu wypisać średnią cenę produktu, wyliczoną dla całej tabeli. --W kolumnie ma być we wszystkich wierszach jednakowa wartość. SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products) AS Srednia FROM Products

Można połączyć każdy rekord z poniższego zestawu rekordów: SELECT ProductID, ProductName, CategoryID, UnitPrice, Srednia FROM Products

z wynikami takiego zapytania: SELECT AVG(UnitPrice) FROM Products

Jaki dać warunek złączenia tych zestawów rekordów? Każdy wiersz z tabeli Products powinien być połączony z każdym (jest tylko jeden!) rekordem z zapytania SELECT AVG(UnitPrice) FROM Products. Możemy to zrobić stosując przecinek w klauzuli FROM („iloczyn kartezjański tabel”): SELECT ProductID, ProductName, CategoryID, UnitPrice, Subquery.Srednia FROM Products AS P, (SELECT AVG(UnitPrice) AS Srednia FROM Products) AS Subquery

Taki sam efekt osiągniemy przez zastosowanie operatora JOIN (INNER JOIN) z warunkiem łączenia rekordów, który jest stale prawdziwy (np. 1 = 1): SELECT ProductID, ProductName, CategoryID, UnitPrice, Srednia FROM Products

Język SQL, cz.4. dr H. Telega

INNER JOIN (SELECT AVG(UnitPrice) AS Srednia FROM Products) AS Sub ON 1 = 1

CROSS JOIN realizuje „iloczyn kartezjański” tabel (produkuje zestaw rekordów, w którym każdy rekord z jednej z łączonych tabel jest złączony z każdym rekordem z drugiej tabeli). SELECT ProductID, ProductName, CategoryID, UnitPrice, S.AveragePrice FROM Products AS P CROSS JOIN (SELECT AVG(UnitPrice) AS AveragePrice FROM Products) AS S --Wypisać dane tylko tych produktów, których cena jest większa od średniej --ceny wyliczonej w całej tabeli SELECT ProductID, ProductName, CategoryID, UnitPrice, S.AveragePrice FROM Products AS P CROSS JOIN (SELECT AVG(UnitPrice) AS AveragePrice FROM Products) AS S WHERE UnitPrice > AveragePrice --Dla każdego produktu wypisać jaka jest średnia cena --produktów w kategorii, do której produkt należy SELECT ProductID, ProductName, CategoryID, UnitPrice, (SELECT AVG(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS Srednia FROM Products AS P1 SELECT ProductID, ProductName, P.CategoryID, UnitPrice, S.AveragePrice FROM Products AS P JOIN (SELECT CategoryID, AVG(UnitPrice) AS AveragePrice FROM Products GROUP BY CategoryID) AS S ON P.CategoryID = S.CategoryID

Zamiana podzapytania w klauzuli SELECT na odpowiednią wersję w klauzuli FROM może dać lepszy plan wykonania (ale trzeba to zawsze sprawdzić). Dzieje się tak szczególnie, gdy między SELECT a FROM umieszczamy więcej niż jedno podzapytanie. Można to często zamienić na złączenie z jednym podzapytaniem. Przykład (*): Poniższa konstrukcja nie jest poprawna (w systemie Microsoft SQL Server). Podzapytanie SELECT w tym miejscu musi zwracać pojedynczą wartość. SELECT ProductID, ProductName, CategoryID, (SELECT AVG(UnitPrice) AS AveragePriceInCategory, MIN(UnitPrice) AS MinimumPriceInCategory, MAX(UnitPrice) AS MaximumPriceInCategory, COUNT(*) AS NumberOfProductsInCategory FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) FROM Products AS P1

Jedno z rozwiązań może być takie:

Język SQL, cz.4. dr H. Telega

SELECT ProductID, ProductName, CategoryID, (SELECT AVG(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS AveragePriceInCategory, (SELECT MIN(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS MinimumPriceInCategory, (SELECT MAX(UnitPrice) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS MaximumPriceInCategory, (SELECT COUNT(*) FROM Products AS P2 WHERE P2.CategoryID = P1.CategoryID) AS NumberOfProductsInCategory FROM Products AS P1

Lepiej jednak zamienić to na następującą konstrukcję: SELECT ProductID, ProductName, P.CategoryID, AveragePriceInCategory,MinimumPriceInCategory, MaximumPriceInCategory,NumberOfProductsInCategory FROM Products AS P JOIN (SELECT CategoryID, AVG(UnitPrice) AS AveragePriceInCategory, MIN(UnitPrice) AS MinimumPriceInCategory, MAX(UnitPrice) AS MaximumPriceInCategory, COUNT(*) AS NumberOfProductsInCategory FROM Products AS P2 GROUP BY CategoryID) AS Subquery ON P.CategoryID = Subquery.CategoryID

Porównajmy plany wykonania obydwu powyższych zapytań (rysunek przedstawia fragmenty planów proszę zwrócić uwagę na procentowe porównanie kosztów):

Można rozważyć również zastosowanie operatora CROSS APPLY. W tym przypadku uzyskamy dalsze zmniejszenie kosztu wykonania zapytania (zależy to jednak od indeksów i generalnie od fizycznej budowy tabeli): SELECT ProductID, ProductName, P1.CategoryID, AveragePriceInCategory,MinimumPriceInCategory, MaximumPriceInCategory,NumberOfProductsInCategory

Język SQL, cz.4. dr H. Telega

FROM Products AS P1 CROSS APPLY (SELECT AVG(UnitPrice) AS AveragePriceInCategory, MIN(UnitPrice) AS MinimumPriceInCategory, MAX(UnitPrice) AS MaximumPriceInCategory, COUNT(*) AS NumberOfProductsInCategory FROM Products AS P2 WHERE P1.CategoryID = P2.CategoryID) AS Subquery

Porównanie kosztów operatora JOIN i CROSS APPLY w tym konkretnym przypadku: SELECT ProductID, ProductName, P.CategoryID, AveragePriceInCategory,MinimumPriceInCategory, MaximumPriceInCategory,NumberOfProductsInCategory FROM Products AS P JOIN (SELECT CategoryID, AVG(UnitPrice) AS AveragePriceInCategory, MIN(UnitPrice) AS MinimumPriceInCategory, MAX(UnitPrice) AS MaximumPriceInCategory, COUNT(*) AS NumberOfProductsInCategory FROM Products AS P2 GROUP BY CategoryID) AS Subquery ON P.CategoryID = Subquery.CategoryID SELECT ProductID, ProductName, P1.CategoryID, AveragePriceInCategory,MinimumPriceInCategory, MaximumPriceInCategory,NumberOfProductsInCategory FROM Products AS P1 CROSS APPLY (SELECT AVG(UnitPrice) AS AveragePriceInCategory, MIN(UnitPrice) AS MinimumPriceInCategory, MAX(UnitPrice) AS MaximumPriceInCategory, COUNT(*) AS NumberOfProductsInCategory FROM Products AS P2 WHERE P1.CategoryID = P2.CategoryID) AS Subquery

Przykład ten będzie jeszcze rozwiązany poniżej przy pomocy Common Table Expression.

Język SQL, cz.4. dr H. Telega

5. Wprowadzenie do Common Table Expressions (CTE). Jeśli zapytanie A odwołuje się do pewnego innego zapytania B (być może robi to więcej niż jeden raz), to można zapytanie B „wyciągnąć” przed zapytanie A. Trochę przypomina to wyciąganie pewnego wspólnego czynnika przed nawias przy dodawaniu: x*b + y*b = b*(x + y) oczywiście analogia nie jest dosłowna. Możemy zdefiniować jakieś zdanie SELECT jako wspólne wyrażenie (lub wyrażenia), do którego (lub których) odwołuje się zdanie SELECT występujące bezpośrednio po definicji wyrażenia wspólnego. To wyrażenie wspólne nazywa się w języku SQL Common Table Expression (CTE). Proste wykorzystanie CTE może wyglądać tak: ;WITH KlienciZNiemiec (IdKlienta, NazwaKlienta, Miejscowość, Kraj) AS (SELECT CustomerID, CompanyName, City, Country FROM Customers WHERE Country = N'Germany') SELECT * FROM KlienciZNiemiec JOIN Orders AS O ON KlienciZNiemiec.IdKlienta = O.CustomerID ;WITH KlienciZNiemiec (IdKlienta, NazwaKlienta, Miejscowość, Kraj) AS (SELECT CustomerID, CompanyName, City, Country FROM Customers WHERE Country = N'Germany') SELECT Miejscowość, COUNT(*) FROM KlienciZNiemiec GROUP BY Miejscowość

Przypomina to tworzenie widoku, który jednak nie jest na trwałe zapamiętany w bazie danych, tylko jest wykorzystany w jednym zdaniu SELECT. Przed słowem WITH warto stawiać średnik. Dlaczego? Rozważmy następujący przykład: SELECT ProductID, ProductName, CategoryID, UnitPrice, Srednia FROM Products CROSS JOIN (SELECT AVG(UnitPrice) AS Srednia FROM Products) AS Sub ;WITH CTE AS (SELECT AVG(UnitPrice) AS Srednia FROM Products) SELECT ProductID, ProductName, CategoryID, UnitPrice, CTE.Srednia FROM Products CROSS JOIN CTE

Zdanie bezpośrednio poprzedzające CTE zawiera klauzulę FROM. W języku Transact-SQL w klauzuli WHERE można wpisywać tzw. hints (wskazówki), które mogą dotyczyć na przykład wykorzystania pewnego indeksu przy realizacji klauzuli WHERE. Robi się to przez dodanie słowa kluczowego WITH, po którym w nawiasach wpisujemy nazwę indeksu: WITH (INDEX = IX_nazwa). Średnik przed CTE wskazuje, że słowo WITH nie jest użyte jako wskazówka w poprzedzającym zdaniu SQL, tylko jest to początek definicji Common Table Expression. Formalnie wystarczy po prostu poprzedzające zdanie SELECT zakończyć średnikiem, jednak często w zapisach CTE średnik pojawia się „dla bezpieczeństwa” przed słowem WITH. Rozwiązanie przy pomocy CTE wcześniej przedstawionego przykładu oznaczonego (*)

Język SQL, cz.4. dr H. Telega

;WITH CTE AS (SELECT CategoryID, AVG(UnitPrice) AS AveragePriceInCategory, MIN(UnitPrice) AS MinimumPriceInCategory, MAX(UnitPrice) AS MaximumPriceInCategory, COUNT(*) AS NumberOfProductsInCategory FROM Products AS P2 GROUP BY CategoryID) SELECT ProductID, ProductName, P.CategoryID, AveragePriceInCategory,MinimumPriceInCategory, MaximumPriceInCategory,NumberOfProductsInCategory FROM Products AS P JOIN CTE ON P.CategoryID = CTE.CategoryID

Koszt będzie podobny jak w przypadku złączenia z podzapytaniem. Po słownie WITH można zdefiniować więcej niż jedno wyrażenie CTE, należy te wyrażenia oddzielić przecinkami. W każdym kolejnym można odwoływać się do poprzednich. Przykład: Wyświetlić dane wszystkich produktów, które należą do tych kategorii, w których jest najwyższa średnia cena jednostkowa. Może się zdarzyć, że dwie lub więcej kategorie mają taką samą średnią cenę jednostkową i jest to najwyższa średnia cena jednostkowa wśród średnich cen w kategoriach. ;WITH AVGPricesInCategoriesCTE AS ( SELECT CategoryID, AVG(UnitPrice) AverageUnitPrice FROM Products GROUP BY CategoryID ) , MaxAVGCTE AS ( SELECT MAX(AverageUnitPrice) AS MaximumAverageUnitPrice FROM AVGPricesInCategoriesCTE) SELECT * FROM Products AS P WHERE P.CategoryID IN (SELECT CategoryID FROM AVGPricesInCategoriesCTE CROSS JOIN MaxAVGCTE WHERE AverageUnitPrice = MaximumAverageUnitPrice )

Przy użyciu CTE można pisać zdania rekurencyjne w SQL.

6. Operatory IN, NOT IN, EXISTS. Operator IN --Wypisać wszystkie dane produktów o identyfikatorach (numerach): 1,3,5 i 12.

Można to zrobić tak: SELECT * FROM Products WHERE ProductID =1 OR ProductID = 3 OR ProductID = 5 OR ProductID = 12

lub wykorzystać operator IN: SELECT * FROM Products WHERE ProductID IN (1,3,5,12)

Język SQL, cz.4. dr H. Telega

Prawy argument operatora IN może być podzapytaniem. --Wypisać wszystkie dane pracowników, którzy mają zarejestrowane chociaż jedno --zwolnienie chorobowe w tabeli Zwolnienia SELECT * FROM Pracownicy WHERE IdPracownika IN (SELECT IdPracownika FROM Zwolnienia) --Wypisać wszystkie dane pracowników, którzy NIE mają zarejestrowanego żadnego --zwolnienia chorobowe w tabeli Zwolnienia

Można wykorzystać operator NOT IN: SELECT * FROM Pracownicy WHERE IdPracownika NOT IN (SELECT IdPracownika FROM Zwolnienia)

Inne rozwiązanie, równoważne powyższemu polega na wykorzystaniu dwóch operatorów logicznych: IN oraz NOT. Jest to przedstawione poniżej. SELECT * FROM Pracownicy WHERE NOT (IdPracownika IN (SELECT IdPracownika FROM Zwolnienia))

Proszę zwrócić uwagę na istotne różnice. Operator NOT IN ma dwa argumenty, które muszą być wpisane z lewej strony (jeden) i z prawej strony (drugi) operatora. Operator NOT ma tylko jeden argument, który musi być wpisany z prawej strony operatora. --Wypis...


Similar Free PDFs