Пример 19.11. Найти номера отделов и средний возраст служащих для таких отделов, что найдется хотя бы один другой отдел, средний возраст служащих которого больше, чем в данном.
SELECT DEPT_NO, AVG (CURRENT_DATE – EMP_BDATE) FROM EMP WHERE DEPT_NO IS NOT NULL GROUP BY DEPT_NO HAVING AVG (CURRENT_DATE – EMP_BDATE)< SOME (SELECT AVG (CURRENT_DATE – EMP1.EMP_BDATE) FROM EMP EMP1 WHERE EMP1.DEPT_NO IS NOT NULL GROUP BY EMP1.DEPT_NO);
Напомним, что «ниладическая» функция CURRENT_DATE выдает текущую дату, и, следовательно, значением выражения CURRENT_DATE – EMP_BDATE является интервал, представляющий текущий возраст служащего. На наш взгляд, формулировка этого запроса несколько упрощается, если пользоваться предикат предикатом EXISTS (пример 19.11.1):
SELECT DEPT_NO, AVG (CURRENT_DATE – EMP_BDATE) FROM EMP WHERE DEPT_NO IS NOT NULL GROUP BY DEPT_NO HAVING EXISTS (SELECT EMP1.DEPT_NO FROM EMP EMP1 WHERE EMP1.DEPT_NO IS NOT NULL GROUP BY EMP1.DEPT_NO HAVING AVG (CURRENT_DATE – EMP1.EMP_BDATE) > AVG (CURRENT_DATE – EMP.EMP_BDATE));
Пример 19.12. Найти номера отделов и средний возраст служащих для отделов с минимальным средним возрастом служащих.
SELECT DEPT_NO, AVG (CURRENT_DATE – EMP_BDATE) FROM EMP WHERE DEPT_NO IS NOT NULL GROUP BY DEPT_NO HAVING AVG (CURRENT_DATE – EMP_BDATE) <= ALL (SELECT AVG (CURRENT_DATE – EMP_BDATE) FROM EMP WHERE DEPT_NO IS NOT NULL GROUP BY DEPT_NO);
Этот запрос легко формулируется в более понятном виде с использованием предиката NOT EXISTS (пример 19.12.1):
SELECT DEPT_NO, AVG (CURRENT_DATE – EMP_BDATE) FROM EMP WHERE DEPT_NO IS NOT NULL GROUP BY DEPT_NO HAVING NOT EXISTS (SELECT EMP1.DEPT_NO FROM EMP EMP1 WHERE EMP1.DEPT_NO IS NOT NULL GROUP BY EMP1.DEPT_NO HAVING AVG (CURRENT_DATE – EMP1.EMP_BDATE) < AVG (CURRENT_DATE – EMP.EMP_BDATE));