Solución
Base de datos
Estrategía 1: UNION
Intuición
La estrategía de UNION
combina dos conjuntos distintos de lógica usando el operador UNION
. Aquí está la
intuición detrás de cada parte:
Paso 1 - Filtrar los empleados con primary_flag = ‘Y’:
SELECT
employee_id,
department_id
FROM
Employee
WHERE
primary_flag = 'Y'
- Esta parte filtra a aquellos empleados que han sido marcados explicitamente como que tienen un departamento concreto como principal.
- En el caso de los empleados que pertenecen a varios departamentos, uno de ellos tendrá el indicador
primary_flag
con el valor ‘Y’, lo que indica qu es el departamento principal. - El código SQL busca
employee_id
ydepartment_id
dondeprimary_flag
es ‘Y’.
Paso 2 - Filtrar los empleados que aparecen exactamente una vez en la tabla Employee:
SELECT
employee_id,
department_id
FROM
Employee
GROUP BY
employee_id
HAVING
COUNT(employee_id) = 1
- El objetivo aquí es capturar a los empleados que están asociados a un solo departamento. En estos casos, ese único departamento es automáticamente su departamento principal.
- El código agrupa los registros de la tabla Employee por
employee_id
utilizandoGROUP BY
. Para cada ID de empleado, comprueba el recuento de filas asociadas (o departamentos). - La cláusula
HAVING
filtra los grupos en los que el recuento de filas (es decir, departamentos) de ese empleado no es igual a 1. - De esta forma, sólo se seleccionan aquellos empleados que están asociados a un único departamento.
Paso 3 - Combinar ambos resultados con UNION:
SELECT
employee_id,
department_id
FROM
Employee
WHERE
primary_flag = 'Y'
UNION
SELECT
employee_id,
department_id
FROM
Employee
GROUP BY
employee_id
HAVING
COUNT(employee_id) = 1;
UNION
es un operador SQL que combina los resultados de dos sentenciasSELECT
en un único conjunto de filas. Elimina automáticamente los duplicados.- Aquí se utiliza para combinar los resultados de las dos lógicas mencionadas: las que tienen
primary_flag = 'Y'
y las que sólo aparecen una vez en la tabla. - El resultado final es una lista unificada que contiene el departamento principal de cada empleado
En esencia, el código SQL garantiza que, para cada empleado, o bien se selecciona su departamento principal marcado explícitamente, o bien, si sólo pertenece a un departamento, se elige ese departamento como principal.
Implementación
En base a lo anterior, la solución puede ser implementada como sigue:
-- Filtra empleados con primary_flag = 'Y'
SELECT
employee_id,
department_id
FROM
Employee
WHERE
primary_flag = 'Y'
UNION
-- Filtra empleados que aparecen exactamente una vez en la tabla Employee
SELECT
employee_id,
department_id
FROM
Employee
GROUP BY
employee_id
HAVING
COUNT(employee_id) = 1;
Estrategía 2: Window Function (COUNT)
Intuición
Este enfoque utiliza una función avanzada de SQL denominada “funciones ventana”, concretamente COUNT() OVER()
.
He aquí la intuición de cada paso:
Paso 1 - Consulta interna con función ventana:
SELECT
*,
COUNT(employee_id) OVER(PARTITION BY employee_id) AS EmployeeCount
FROM
Employee
- Esta consulta obtiene todas las columnas de la tabla Employee y añade una nueva columna computada,
EmployeeCount
. COUNT(employee_id) OVER(PARTITION BY employee_id)
es una función de ventana. Veamos lo que hace:PARTITION BY employee_id
: Esto descompone los datos en “ventanas” o “particiones” de filas que tienen el mismoemployee_id
. Cada ventana es básicamente una subsección de los datos de un empleado concreto.COUNT(employee_id) OVER(...)
: Esto cuenta el número de filas (es decir, el número de departamentos) para cada empleado dentro de su respectiva partición/ventana. El resultado es una nueva columna, EmployeeCount, que nos indica con cuántos departamentos está asociado cada empleado. Este recuento se repite para cada fila del mismo empleado.
Paso 2 - Alias y consulta externa:
SELECT
employee_id,
department_id
FROM
EmployeePartition
- El resultado de la consulta interna se trata como una tabla temporal llamada EmployeePartition.
- De esta tabla, seleccionamos las columnas deseadas:
employee_id
ydepartment_id
.
Paso 3 - Filtrado con la cláusula WHERE:
WHERE
EmployeeCount = 1
OR primary_flag = 'Y'
- Tenemos dos condiciones para filtrar el departamento principal para cada empleado:
EmployeeCount = 1
: Esto captura aquellos empleados que pertenecen a un solo departamento. Para ellos, ese único departamento es automáticamente su departamento principal.primary_flag = 'Y'
: Esto captura a los empleados que pertenecen a múltiples departamentos pero tienen un departamento explícitamente marcado como primario con una bandera ‘Y’.
- Se utiliza el operador
OR
, por lo que cualquier fila que cumpla cualquiera de las condiciones anteriores se incluye en el resultado.
Resumen:
El código asigna primero un recuento de departamento de empleado a cada fila utilizando una función de ventana. A continuación, filtra las filas deseadas en función de si un empleado está asociado a un solo departamento o tiene un departamento marcado explícitamente como principal. El resultado final es una lista de los departamentos principales de cada empleado.
Implementación
En base a lo anterior, la solución puede ser implementada como sigue:
SELECT
employee_id,
department_id
FROM
(
SELECT
*,
COUNT(employee_id) OVER(PARTITION BY employee_id) AS EmployeeCount
FROM
Employee
) EmployeePartition
WHERE
EmployeeCount = 1
OR primary_flag = 'Y';