Podzapytania w języku SQL

Podzapytania zagnieżdżone w języku SQL

Podzapytanie zagnieżdżone SELECT znajduje się wewnątrz zewnętrznego zapytania SELECT, np. po klauzuli WHERE, HAVING lub FROM. W przypadku tego rodzaju zapytań w pierwszej kolejności wykonywane są wewnętrzne zapytania SELECT, a ich wynik jest wykorzystywany do zewnętrznego zapytania SELECT.

W przypadku zapytań zagnieżdżonych w wewnętrznym zapytaniu SELECT nie może wystąpić klauzula ORDER BY ani operatory UNION, INTERSECT, MINUS (EXCEPT).

UWAGA: należy zwrócić uwagę, czy zapytania wewnętrzne zwracają jeden wynik czy wiele wartości. Jeśli zwracają wiele wartości, to w warunku WHERE zapytania wewnętrznego należy użyć operatora IN lub operatorów ALL lub ANY. Na końcu zapytania wewnętrznego nie ma średnika, zapisuje się je w nawiasach okrągłych.

Operatory ALLANY można stosować w podzapytaniach zwracających więcej niż jeden wiersz. Podaje się je w klauzuli WHEREHAVING razem z operatorami porównywania.

Operator ANY: wiersz/krotka/rekord zostanie wybrany, jeśli wyrażenie jest zgodne z co najmniej jedną wartością wybraną w podzapytaniu wewnętrznym.

Operator ALL: warunek musi być spełniony przez wszystkie wartości wybrane w podzapytaniu.

Przykład: z bazy firma z tabeli emp wybrać imiona i nazwiska pracowników, którzy zarabiają więcej niż średnia płaca w firmie.

SELECT first_name AS imie, last_name AS nazwisko, salary AS placa
FROM emp
WHERE salary>(SELECT AVG(salary)
	FROM emp)
ORDER BY nazwisko, imie;

Klauzula ORDER BY w zapytaniu SELECT może wystąpić tylko raz na końcu zewnętrznego zapytania SELECT.

Przykład: z bazy danych firma z tabeli emp wybrać imiona, nazwiska, wynagrodzenie, ID departamentu pracowników, którzy mają najwyższe wynagrodzenia w tym departamencie.

SELECT first_name, last_name, salary, dept_id
FROM emp
WHERE (salary, dept_id) IN (SELECT MAX(salary), dept_id
	FROM emp
	GROUP BY dept_id)
ORDER BY salary DESC;

Podzapytania skorelowane

Podzapytania skorelowane są szczególnym przypadkiem zapytań zagnieżdżonych. W przypadku zapytań zagnieżdżonych w pierwszej kolejności wykonywane jest zapytanie wewnętrzne, a jego wynik wykorzystywany jest do zapytania zewnętrznego, natomiast w przypadku podzapytań skorelowanych dla każdego wystąpienia zapytania zewnętrznego wykonywane jest zapytanie wewnętrzne, jeśli spełniony jest warunek zawarty w klauzuli WHERE lub HAVING. Wynik zapytania zewnętrznego brany jest pod uwagę.

Przykład: z bazy danych pobierz: nazwę departamentu, nazwisko, imię i wynagrodzenie pracowników, którzy mają najwyższe wynagrodzenie w tym departamencie.

SELECT Ez.dept_id, Ez.last_name, Ez.first_name, Ez.salary
FROM emp Ez
WHERE Ez.salary=(SELECT MAX(Ew.salary)
	FROM emp Ew
	WHERE Ez.dept_id = Ew.dept_id)
ORDER BY Ez.dept_id;

W przypadku tego zapytania skorelowanego tworzone jest zapytanie zewnętrzne (nadrzędne) odczytujące wszystkie rekordy z tabeli emp. Następnie dla pierwszego odczytanego rekordu wykonywane jest zapytanie podrzędne (podzapytanie) znajdujące wartość płacy maksymalnej dla tego departamentu, którego ID został odczytany w rozpatrywanym rekordzie zapytania głównego, co jest możliwe dzięki wykonywaniu porównania w wewnętrznej klauzuli WHERE łączącego wyniki zapytań zewnętrznego i podzapytania. Jesli wartość wynagrodzenia odczytana w zapytaniu zewnętrznym jest równa maksymalnej płacy obliczonej w zapytaniu wewnętrznym, to rekord z zapytania głównego brany jest pod uwagę. W przeciwnym wypadku jest odrzucany. Powyższa procedura powtarzana jest dla każdego rekordu wybranego w zapytaniu wewnętrznym.

Operator EXISTS

W przypadku zapytań skorelowanych czasami interesuje nas tylko, czy wiersz spełniający podane warunki istnieje. Wtedy używamy operatora EXISTS.

Przykład: z bazy danych firma wypisać nazwy departamentów, w których aktualnie nikt nie pracuje.

SELECT D.name
FROM dept D
WHERE NOT EXISTS(SELECT 1
	FROM emp Ew
	WHERE Ew.dept=id = D.id
	LIMIT 1)
ORDER BY D.name;

UWAGA: w przypadku operatora EXISTS chcemy sprawdzić, czy rekord spełniający podany warunek istnieje, dlatego po klauzuli SELECT można napisać * lub dowolną stałą.


Przykład: z bazy danych pobrać imiona i nazwiska pracowników, których wynagrodzenie jest wyższe niż większe niż najwyższe wynagrodzenie pracownika w departamencie 10. Użyć operatora ALL.

SELECT Ez.first_name, Ez.last_name, Ez.salary
FROM emp Ez
WHERE Ez.salary > ALL(SELECT Ew.salary
	FROM emp Ew
	WHERE Ew.dept_id = 10)
ORDER BY Ez.last_name, Ez.first_name;

Przykład: z bazy danych firma pobrać imiona i nazwiska pracowników, którzy pracują na tym samym stanowisku, co Adam Krzywy i mają wyższe wynagrodzenia niż Agata Prosta.

SELECT Ez.first_name, Ez.last_name
FROM emp Ez
WHERE Ez.title = (SELECT Ew.title
		FROM emp Ew
		WHERE Ew.first_name = 'Adam'
			AND Ew.last_name = 'Krzywy')
	AND Ez.salary > (SELECT Ew.salary
		FROM emp Ew
		WHERE Ew.first_name = 'Agata'
			AND Ew.last_name = 'Prosta')
ORDER BY Ez.last_name, Ez.first_name;

Przykład: z bazy danych pobrać nazwy departamentów, w których pracują pracownicy na stanowisku Clerk [z j. ang. urzędnik].

SELECT D.name
FROM dept D
WHERE D.id IN (SELECT Ew.dept_id
	FROM emp Ew
	WHERE Ew.title = 'Clerk')

 

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.