SQL. Problemas interesantes

¡Hola, Habr!

Desde hace más de 3 años, he estado enseñando SQL en diferentes centros de capacitación, y una de mis observaciones es que los estudiantes aprenden y comprenden SQL mejor cuando se les presenta un problema, en lugar de simplemente hablarles sobre las posibilidades y fundamentos teóricos.

En este artículo, compartiré con ustedes mi lista de problemas que doy a los estudiantes como tarea y sobre los cuales realizamos diferentes tipos de tormentas de ideas, lo que conduce a una comprensión profunda y clara de SQL.

SQL. Problemas interesantes

SQL (ˈɛsˈkjuˈɛl; inglés: structured query language — "lenguaje de consulta estructurado") es un lenguaje de programación declarativo utilizado para crear, modificar y gestionar datos en una base de datos relacional, administrada por el correspondiente sistema de gestión de bases de datos. Más información...

Se puede leer sobre SQL en diferentes fuentes.
Este artículo no tiene el objetivo de enseñarte SQL desde cero.

Así que, ¡empecemos!

Usaremos la famosa esquema HR en Oracle con sus tablas (Más información):

SQL. Problemas interesantes
Cabe destacar que solo consideraremos problemas sobre SELECT. No hay problemas sobre DML y DDL.

Tareas

Restringir y ordenar datos

Tabla Employees. Obtener una lista con información sobre todos los empleados
Solución

SELECT * FROM employees

Tabla Employees. Obtener una lista de todos los empleados con el nombre 'David'
Solución

SELECT *
  FROM employees
 WHERE first_name = 'David';

Tabla Employees. Obtener una lista de todos los empleados con job_id igual a 'IT_PROG'
Solución

SELECT *
  FROM employees
 WHERE job_id = 'IT_PROG'

Tabla Employees. Obtener una lista de todos los empleados del departamento 50 (department_id) con un salario (salary) mayor a 4000
Solución

SELECT *
  FROM employees
 WHERE department_id = 50 AND salary > 4000;

Tabla Employees. Obtener una lista de todos los empleados del departamento 20 y del departamento 30 (department_id)
Solución

SELECT *
  FROM employees
 WHERE department_id = 20 OR department_id = 30;

Tabla Employees. Obtener una lista de todos los empleados cuyo último carácter en el nombre es 'a'
Solución

SELECT *
  FROM employees
 WHERE first_name LIKE '%a';

Tabla Employees. Obtener una lista de todos los empleados de los departamentos 50 y 80 (department_id) que tienen bonificación (valor en la columna commission_pct no nulo)
Solución

SELECT *
  FROM employees
 WHERE     (department_id = 50 OR department_id = 80)
       AND commission_pct IS NOT NULL;

Tabla Employees. Obtener una lista de todos los empleados cuyos nombres contienen al menos 2 letras 'n'
Solución

SELECT *
  FROM employees
 WHERE first_name LIKE '%n%n%';

Tabla Employees. Obtener una lista de todos los empleados cuyos nombres tienen más de 4 letras
Solución

SELECT *
  FROM employees
 WHERE first_name LIKE '%_____%';

Tabla de Empleados. Obtener una lista de todos los empleados cuyos salarios están entre 8000 y 9000 (inclusive)
Solución

SELECT *
  FROM employees
 WHERE salary BETWEEN 8000 AND 9000;

Tabla de Empleados. Obtener una lista de todos los empleados cuyo nombre contiene el símbolo ‘%’
Solución

SELECT *
  FROM employees
 WHERE first_name LIKE '%%%' ESCAPE '';

Tabla de Empleados. Obtener una lista de todos los ID de los gerentes
Solución

SELECT DISTINCT manager_id
  FROM employees
 WHERE manager_id IS NOT NULL;

Tabla de Empleados. Obtener una lista de trabajadores con sus posiciones en formato: Donald(sh_clerk)
Solución

SELECT first_name || '(' || LOWER (job_id) || ')' employee FROM employees;

Uso de funciones de fila única para personalizar la salida

Tabla de Empleados. Obtener una lista de todos los empleados cuyos nombres tienen más de 10 letras
Solución

SELECT *
  FROM employees
 WHERE LENGTH (first_name) > 10;

Tabla de Empleados. Obtener una lista de todos los empleados cuyo nombre contiene la letra ‘b’ (sin distinción de mayúsculas y minúsculas)
Solución

SELECT *
  FROM employees
 WHERE INSTR (LOWER (first_name), 'b') > 0;

Tabla de Empleados. Obtener una lista de todos los empleados cuyos nombres contienen al menos 2 letras ‘a’
Solución

SELECT *
  FROM employees
 WHERE INSTR (LOWER (first_name),'a',1,2) > 0;

Tabla de Empleados. Obtener una lista de todos los empleados cuyos salarios son múltiplos de 1000
Solución

SELECT *
  FROM employees
 WHERE MOD (salary, 1000) = 0;

Tabla de Empleados. Obtener los primeros 3 dígitos del número de teléfono del empleado si su número está en el formato XXX.XXX.XXXX
Solución

SELECT phone_number, SUBSTR (phone_number, 1, 3) new_phone_number
  FROM employees
 WHERE phone_number LIKE '___.___.____';

Tabla de Departamentos. Obtener la primera palabra del nombre del departamento para aquellos cuyos nombres tienen más de una palabra
Solución

SELECT department_name,
       SUBSTR (department_name, 1, INSTR (department_name, ' ')-1)
           first_word
  FROM departments
 WHERE INSTR (department_name, ' ') > 0;

Tabla de Empleados. Obtener los nombres de los empleados sin la primera y última letra del nombre
Solución

SELECT first_name, SUBSTR (first_name, 2, LENGTH (first_name) - 2) new_name
  FROM employees;

Tabla de Empleados. Obtener una lista de todos los empleados cuya última letra del nombre es ‘m’ y cuya longitud del nombre es mayor de 5
Solución

SELECT *
  FROM employees
 WHERE SUBSTR (first_name, -1) = 'm' AND LENGTH(first_name)>5;

Tabla Dual. Obtener la fecha del próximo viernes
Solución

SELECT NEXT_DAY (SYSDATE, 'FRIDAY') next_friday FROM DUAL;

Tabla de Empleados. Obtener una lista de todos los empleados que han trabajado en la empresa durante más de 17 años
Solución

SELECT *
  FROM employees
 WHERE MONTHS_BETWEEN (SYSDATE, hire_date) / 12 > 17;

Tabla de Empleados. Obtener una lista de todos los empleados cuyo último dígito del número de teléfono es impar y consta de 3 números separados por puntos
Solución

SELECT *
  FROM employees
 WHERE     MOD (SUBSTR (phone_number, -1), 2) != 0
       AND INSTR (phone_number,'.',1,3) = 0;

Tabla de Empleados. Obtener la lista de todos los empleados cuyo valor de job_id después del signo '_' tiene al menos 3 caracteres, pero este valor después de '_' no es igual a 'CLERK'
Solución

SELECT *
  FROM employees
 WHERE     LENGTH (SUBSTR (job_id, INSTR (job_id, '_') + 1)) > 3
       AND SUBSTR (job_id, INSTR (job_id, '_') + 1) != 'CLERK';

Tabla de Empleados. Obtener la lista de todos los empleados reemplazando en el valor de PHONE_NUMBER todos los ‘.’ por ‘-‘
Solución

SELECT phone_number, REPLACE (phone_number, '.', '-') new_phone_number
  FROM employees;

Uso de funciones de conversión y expresiones condicionales

Tabla de Empleados. Obtener la lista de todos los empleados que empezaron a trabajar el primer día del mes (cualquiera)
Solución

SELECT *
  FROM employees
 WHERE TO_CHAR (hire_date, 'DD') = '01';

Tabla de Empleados. Obtener la lista de todos los empleados que empezaron a trabajar en el año 2008
Solución

SELECT *
  FROM employees
 WHERE TO_CHAR (hire_date, 'YYYY') = '2008';

Tabla DUAL. Mostrar la fecha de mañana en el formato: Tomorrow is Second day of January
Solución

SELECT TO_CHAR (SYSDATE, 'fm""Tomorrow is ""Ddspth ""day of"" Month') info
  FROM DUAL;

Tabla de Empleados. Obtener la lista de todos los empleados y la fecha de ingreso de cada uno en el formato: 21st of June, 2007
Solución

SELECT first_name, TO_CHAR (hire_date, 'fmddth ""of"" Month, YYYY') hire_date
  FROM employees;

Tabla de Empleados. Obtener la lista de trabajadores con aumentos salariales del 20%. Mostrar el salario con el signo de dólar
Solución

SELECT first_name, TO_CHAR (salary + salary * 0.20, 'fm$999,999.00') new_salary
  FROM employees;

Tabla de Empleados. Obtener la lista de todos los empleados que empezaron a trabajar en febrero de 2007.
Solución

SELECT *
  FROM employees
 WHERE hire_date BETWEEN TO_DATE ('01.02.2007', 'DD.MM.YYYY')
                     AND LAST_DAY (TO_DATE ('01.02.2007', 'DD.MM.YYYY'));

SELECT *
  FROM employees
 WHERE to_char(hire_date,'MM.YYYY') = '02.2007'; 

Tabla DUAL. Mostrar la fecha actual, + segundo, + minuto, + hora, + día, + mes, + año
Solución

SELECT SYSDATE now,
       SYSDATE + 1 / (24 * 60 * 60) plus_second,
       SYSDATE + 1 / (24 * 60) plus_minute,
       SYSDATE + 1 / 24 plus_hour,
       SYSDATE + 1 plus_day,
       ADD_MONTHS (SYSDATE, 1) plus_month,
       ADD_MONTHS (SYSDATE, 12) plus_year
  FROM DUAL;

Tabla de Empleados. Obtener la lista de todos los empleados con salarios completos (salary + commission_pct(%)) en formato: $24,000.00
Solución

SELECT first_name, salary, TO_CHAR (salary + salary * NVL (commission_pct, 0), 'fm$99,999.00') full_salary
  FROM employees;

Tabla de Empleados. Obtener la lista de todos los empleados y la información sobre la existencia de bonificaciones en el salario (Sí/No)
Solución

SELECT first_name, commission_pct, NVL2 (commission_pct, 'Yes', 'No') has_bonus
  FROM employees;

Tabla de Empleados. Obtener el nivel salarial de cada empleado: Menos de 5000 se considera bajo, Mayor o igual a 5000 y menos de 10000 se considera normal, Mayor o igual a 10000 se considera alto
Solución

SELECT first_name,
       salary,
       CASE
           WHEN salary = 5000 AND salary < 10000 THEN 'Normal'
           ELSE 'Alto'
       END salary_level
  FROM employees;

Tabla Countries. Mostrar para cada país la región en la que se encuentra: 1-Europa, 2-América, 3-Asia, 4-África (sin Join)
Solución

SELECT country_name country,
       DECODE (region_id,
               1, 'Europa',
               2, 'América',
               3, 'Asia',
               4, 'África',
               'Desconocido')
           region
  FROM countries;

SELECT country_name
           country,
       CASE region_id
           WHEN 1 THEN 'Europa'
           WHEN 2 THEN 'América'
           WHEN 3 THEN 'Asia'
           WHEN 4 THEN 'África'
           ELSE 'Desconocido'
       END
           region
  FROM countries;

Informes de Datos Agregados Usando Funciones de Grupo

Tabla Employees. Obtener un informe por department_id con el salario mínimo y máximo, con la fecha de contratación más temprana y tardía y con el número de empleados. Ordenar por el número de empleados (en orden descendente)
Solución

  SELECT department_id,
         MIN (salary) min_salary,
         MAX (salary) max_salary,
         MIN (hire_date) min_hire_date,
         MAX (hire_date) max_hire_Date,
         COUNT (*) count
    FROM employees
GROUP BY department_id
order by count(*) desc;

Tabla Employees. ¿Cuántos empleados tienen nombres que comienzan con la misma letra? Ordenar por cantidad. Mostrar solo aquellos donde la cantidad sea mayor que 1
Solución

SELECT SUBSTR (first_name, 1, 1) first_char, COUNT (*)
    FROM employees
GROUP BY SUBSTR (first_name, 1, 1)
  HAVING COUNT (*) > 1
ORDER BY 2 DESC;

Tabla Employees. ¿Cuántos empleados trabajan en el mismo departamento y reciben el mismo salario?
Solución

SELECT department_id, salary, COUNT (*)
    FROM employees
GROUP BY department_id, salary
  HAVING COUNT (*) > 1;

Tabla Employees. Obtener un informe de cuántos empleados fueron contratados cada día de la semana. Ordenar por cantidad
Solución

SELECT TO_CHAR (hire_Date, 'Day') day, COUNT (*)
    FROM employees
GROUP BY TO_CHAR (hire_Date, 'Day')
ORDER BY 2 DESC;

Tabla Employees. Obtener un informe de cuántos empleados fueron contratados por años. Ordenar por cantidad
Solución

SELECT TO_CHAR (hire_date, 'YYYY') year, COUNT (*)
    FROM employees
GROUP BY TO_CHAR (hire_date, 'YYYY');

Tabla Employees. Obtener el número de departamentos en los que hay empleados
Solución

SELECT COUNT (COUNT (*))     department_count
    FROM employees
   WHERE department_id IS NOT NULL
GROUP BY department_id;

Tabla Employees. Obtener una lista de department_id en los que trabajan más de 30 empleados
Solución

  SELECT department_id
    FROM employees
GROUP BY department_id
  HAVING COUNT (*) > 30;

Tabla Employees. Obtener una lista de department_id y el salario medio redondeado de los trabajadores en cada departamento.
Solución

  SELECT department_id, ROUND (AVG (salary)) avg_salary
    FROM employees
GROUP BY department_id;

Tabla Countries. Obtener una lista de region_id con la suma de todas las letras de country_name donde hay más de 60
Solución

  SELECCIONAR region_id
    DE countries
AGRUPAR POR region_id
  TENIENDO SUMA (LONGITUD (country_name)) > 60;

Tabla Employees. Obtener la lista de department_id en la que trabajan empleados con múltiples (>1) job_id
Solución

  SELECCIONAR department_id
    DE employees
AGRUPAR POR department_id
  TENIENDO CONTAR (DISTINCT job_id) > 1;

Tabla Employees. Obtener la lista de manager_id que tienen más de 5 subordinados y la suma de todos los salarios de sus subordinados es mayor a 50000
Solución

  SELECCIONAR manager_id
    DE employees
AGRUPAR POR manager_id
  TENIENDO CONTAR (*) > 5 Y SUMA (salary) > 50000;

Tabla Employees. Obtener la lista de manager_id cuya promedio de salario de todos sus subordinados se encuentra entre 6000 y 9000 y que no reciben bonificaciones (commission_pct vacío)
Solución

  SELECCIONAR manager_id, AVG (salary) avg_salary
    DE employees
   DONDE commission_pct ES NULO
AGRUPAR POR manager_id
  TENIENDO AVG (salary) ENTRE 6000 Y 9000;

Tabla Employees. Obtener el salario máximo de todos los empleados job_id que terminan en la palabra ‘CLERK’
Solución

SELECCIONAR MAX (salary) max_salary
  DE employees
 DONDE job_id LIKE '%CLERK';

SELECCIONAR MAX (salary) max_salary
  DE employees
 DONDE SUBSTR (job_id, -5) = 'CLERK';

Tabla Employees. Obtener el salario máximo entre todos los promedios de salario por departamento
Solución

  SELECCIONAR MAX (AVG (salary))
    DE employees
AGRUPAR POR department_id;

Tabla Employees. Obtener la cantidad de empleados con la misma cantidad de letras en su nombre. Mostrar solo aquellos con una longitud de nombre mayor a 5 y una cantidad de empleados con ese nombre mayor a 20. Ordenar por longitud del nombre
Solución

  SELECCIONAR LONGITUD (first_name), CONTAR (*)
    DE employees
AGRUPAR POR LONGITUD (first_name)
  TENIENDO LONGITUD (first_name) > 5 Y CONTAR (*) > 20
ORDENAR POR LONGITUD (first_name);

  SELECCIONAR LONGITUD (first_name), CONTAR (*)
    DE employees
   DONDE LONGITUD (first_name) > 5
AGRUPAR POR LONGITUD (first_name)
  TENIENDO CONTAR (*) > 20
ORDENAR POR LONGITUD (first_name);

Mostrando datos de múltiples tablas utilizando uniones

Tabla Employees, Departments, Locations, Countries, Regions. Obtener la lista de regiones y la cantidad de empleados en cada región
Solución

  SELECCIONAR region_name, CONTAR (*)
    DE employees e
         UNIR departments d ON (e.department_id = d.department_id)
         UNIR locations l ON (d.location_id = l.location_id)
         UNIR countries c ON (l.country_id = c.country_id)
         UNIR regions r ON (c.region_id = r.region_id)
AGRUPAR POR region_name;

Tabla Employees, Departments, Locations, Countries, Regions. Obtener información detallada sobre cada empleado:
First_name, Last_name, Departament, Job, Street, Country, Region
Solución

SELECCIONAR First_name,
       Last_name,
       Department_name,
       Job_id,
       street_address,
       Country_name,
       Region_name
  DE employees  e
       UNIR departments d ON (e.department_id = d.department_id)
       UNIR locations l ON (d.location_id = l.location_id)
       UNIR countries c ON (l.country_id = c.country_id)
       UNIR regions r ON (c.region_id = r.region_id);

Tabla Employees. Mostrar todos los gerentes que tienen más de 6 subordinados
Solución

  SELECCIONAR man.first_name, CONTAR (*)
    DE empleados emp UNIR empleados man EN (emp.manager_id = man.employee_id)
AGRUPAR POR man.first_name
  TENIENDO CONTAR (*) > 6;

Tabla Empleados. Mostrar todos los empleados que no tienen subordinados.
Solución

SELECCIONAR emp.first_name
  DE empleados emp
       UNIR IZQUIERDA empleados man EN (emp.manager_id = man.employee_id)
 DONDE man.FIRST_NAME ES NULO;

SELECCIONAR first_name
  DE empleados
 DONDE manager_id ES NULO;

Tabla Empleados, Historial_de_trabajos. En la tabla Empleado se almacenan todos los empleados. En la tabla Historial_de_trabajos se almacenan los empleados que han dejado la empresa. Obtener un informe sobre todos los empleados y su estado en la empresa (Trabajando o dejado la empresa con la fecha de salida).
Ejemplo:
first_name | estado
Jennifer | Dejó la empresa el 31 de diciembre de 2006
Clara | Actualmente Trabajando
Solución

SELECCIONAR first_name,
       NVL2 (
           end_date,
           TO_CHAR (end_date, 'fm""Dejó la empresa el"" DD ""de"" Mes, YYYY'),
           'Actualmente Trabajando')
           estado
  DE empleados e UNIR IZQUIERDA historial_de_trabajo j EN (e.employee_id = j.employee_id);

Tabla Empleados, Departamentos, Localizaciones, Países, Regiones. Obtener una lista de empleados que viven en Europa (region_name).
Solución

 SELECCIONAR first_name
  DE empleados
       UNIR departamentos USANDO (department_id)
       UNIR localizaciones USANDO (location_id)
       UNIR países USANDO (country_id)
       UNIR regiones USANDO (region_id)
 DONDE region_name = 'Europa';
 
 SELECCIONAR first_name
  DE empleados e
       UNIR departamentos d EN (e.department_id = d.department_id)
       UNIR localizaciones l EN (d.location_id = l.location_id)
       UNIR países c EN (l.country_id = c.country_id)
       UNIR regiones r EN (c.region_id = r.region_id)
 DONDE region_name = 'Europa';

Tabla Empleados, Departamentos. Mostrar todos los departamentos donde trabajan más de 30 empleados.
Solución

SELECCIONAR department_name, CONTAR (*)
    DE empleados e UNIR departamentos d EN (e.department_id = d.department_id)
AGRUPAR POR department_name
  TENIENDO CONTAR (*) > 30;

Tabla Empleados, Departamentos. Mostrar todos los empleados que no pertenecen a ningún departamento.
Solución

SELECCIONAR first_name
  DE empleados e
       UNIR IZQUIERDA departamentos d EN (e.department_id = d.department_id)
 DONDE d.department_name ES NULO;

SELECCIONAR first_name
  DE empleados
 DONDE department_id ES NULO;

Tabla Empleados, Departamentos. Mostrar todos los departamentos que no tienen ningún empleado.
Solución

SELECCIONAR department_name
  DE empleados e
       UNIR DERECHA departamentos d EN (e.department_id = d.department_id)
 DONDE first_name ES NULO;

Tabla Empleados. Mostrar todos los empleados que no tienen a nadie bajo su mando.
Solución

SELECCIONAR man.first_name
  DE empleados emp
       UNIR DERECHA empleados man EN (emp.manager_id = man.employee_id)
 DONDE emp.FIRST_NAME ES NULO;

Tabla Empleados, Trabajos, Departamentos. Mostrar empleados en el formato: First_name, Job_title, Department_name.
Ejemplo:
First_name | Job_title | Department_name
Donald | Envío | Auxiliar de Envío
Solución

SELECCIONAR first_name, job_title, department_name
  DE empleados e
       UNIR trabajos j EN (e.job_id = j.job_id)
       UNIR departamentos d EN (d.department_id = e.department_id);

Tabla Empleados. Obtener una lista de empleados cuyos gerentes fueron contratados en 2005, pero estos empleados fueron contratados antes de 2005.
Solución

SELECT emp.*
  FROM employees emp JOIN employees man ON (emp.manager_id = man.employee_id)
 WHERE     TO_CHAR (man.hire_date, 'YYYY') = '2005'
       AND emp.hire_date < TO_DATE ('01012005', 'DDMMYYYY');

Tabla de empleados. Obtener una lista de empleados cuyos gerentes fueron contratados en enero de cualquier año y cuya longitud de job_title es mayor a 15 caracteres.
Solución

SELECT emp.*
  FROM employees emp
       JOIN employees man ON (emp.manager_id = man.employee_id)
       JOIN jobs j ON (emp.job_id = j.job_id)
 WHERE TO_CHAR (man.hire_date, 'MM') = '01' AND LENGTH (j.job_title) > 15;

Uso de subconsultas para resolver consultas

Tabla de empleados. Obtener una lista de empleados con el nombre más largo.
Solución

SELECT *
  FROM employees
 WHERE LENGTH (first_name) =
       (SELECT MAX (LENGTH (first_name)) FROM employees);

Tabla de empleados. Obtener una lista de empleados con un salario superior al salario promedio de todos los empleados.
Solución

SELECT *
  FROM employees
 WHERE salary > (SELECT AVG (salary) FROM employees);

Tabla de empleados, departamentos, ubicaciones. Obtener la ciudad en la que los empleados ganan en total menos que en cualquier otra.
Solución

SELECT city
    FROM employees e
         JOIN departments d ON (e.department_id = d.department_id)
         JOIN locations l ON (d.location_id = l.location_id)
GROUP BY city
  HAVING SUM (salary) =
         (  SELECT MIN (SUM (salary))
              FROM employees e
                   JOIN departments d ON (e.department_id = d.department_id)
                   JOIN locations l ON (d.location_id = l.location_id)
          GROUP BY city);

Tabla de empleados. Obtener una lista de empleados cuyos gerentes ganan más de 15000.
Solución

SELECT *
  FROM employees
 WHERE manager_id IN (SELECT employee_id
                        FROM employees
                       WHERE salary > 15000)

Tabla Empleados, Departamentos. Mostrar todos los departamentos que no tienen ningún empleado.
Solución

SELECT *
  FROM departments
 WHERE department_id NOT IN (SELECT department_id
                               FROM employees
                              WHERE department_id IS NOT NULL);

Tabla de empleados. Mostrar todos los empleados que no son gerentes.
Solución

SELECT *
  FROM employees
 WHERE employee_id NOT IN (SELECT manager_id
                             FROM employees
                            WHERE manager_id IS NOT NULL);

Tabla Employees. Mostrar todos los gerentes que tienen más de 6 subordinados
Solución

SELECT *
  FROM employees e
 WHERE (SELECT COUNT (*)
          FROM employees
         WHERE manager_id = e.employee_id) > 6;

Tabla de empleados, departamentos. Mostrar empleados que trabajan en el departamento de IT.
Solución

SELECT *
  FROM employees
 WHERE department_id = (SELECT department_id
                          FROM departments
                         WHERE department_name = 'IT');

Tabla Empleados, Trabajos, Departamentos. Mostrar empleados en el formato: First_name, Job_title, Department_name.
Ejemplo:
First_name | Job_title | Department_name
Donald | Envío | Auxiliar de Envío
Solución

SELECT first_name,
       (SELECT job_title
          FROM jobs
         WHERE job_id = e.job_id)
           job_title,
       (SELECT department_name
          FROM departments
         WHERE department_id = e.department_id)
           department_name
  FROM employees e;

Tabla Empleados. Obtener una lista de empleados cuyos gerentes fueron contratados en 2005, pero estos empleados fueron contratados antes de 2005.
Solución

SELECT *
  FROM employees
 WHERE     manager_id IN (SELECT employee_id
                            FROM employees
                           WHERE TO_CHAR (hire_date, 'YYYY') = '2005')
       AND hire_date < TO_DATE ('01012005', 'DDMMYYYY');

Tabla de empleados. Obtener una lista de empleados cuyos gerentes fueron contratados en enero de cualquier año y cuya longitud de job_title es mayor a 15 caracteres.
Solución

SELECT *
  FROM employees e
 WHERE     manager_id IN (SELECT employee_id
                            FROM employees
                           WHERE TO_CHAR (hire_date, 'MM') = '01')
       AND (SELECT LENGTH (job_title)
              FROM jobs
             WHERE job_id = e.job_id) > 15;

Eso es todo por ahora.

Espero que las tareas hayan sido interesantes y emocionantes.
Agregaré a esta lista de tareas siempre que pueda.
También estaré encantado de recibir cualquier comentario o sugerencia.

P.D.: Si a alguien se le ocurre una tarea interesante sobre SELECT, escríbeme en los comentarios, la agregaré a la lista.

Gracias.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster