Deseo escribir una consulta SQL para encontrar el número de días hábiles únicos para cada empleado de la tabla times
.
*---------------------------------------*
|emp_id task_id start_day end_day |
*---------------------------------------*
| 1 1 'monday' 'wednesday' |
| 1 2 'monday' 'tuesday' |
| 1 3 'friday' 'friday' |
| 2 1 'monday' 'friday' |
| 2 1 'tuesday' 'wednesday' |
*---------------------------------------*
Rendimiento esperado:
*-------------------*
|emp_id no_of_days |
*-------------------*
| 1 4 |
| 2 5 |
*-------------------*
He escrito la consulta sqlfiddle que me está dando el expected
resultado, pero por curiosidad, ¿hay una mejor manera de escribir esta consulta? ¿Puedo usar el calendario o la tabla de conteo?
with days_num as
(
select
*,
case
when start_day = 'monday' then 1
when start_day = 'tuesday' then 2
when start_day = 'wednesday' then 3
when start_day = 'thursday' then 4
when start_day = 'friday' then 5
end as start_day_num,
case
when end_day = 'monday' then 1
when end_day = 'tuesday' then 2
when end_day = 'wednesday' then 3
when end_day = 'thursday' then 4
when end_day = 'friday' then 5
end as end_day_num
from times
),
day_diff as
(
select
emp_id,
case
when
(end_day_num - start_day_num) = 0
then
1
else
(end_day_num - start_day_num)
end as total_diff
from days_num
)
select emp_id,
sum(total_diff) as uniq_working_days
from day_diff
group by
emp_id
Cualquier sugerencia seria genial.
sql
sql-server
celoso
fuente
fuente
(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'monday', 'tuesday');
empid_1 ha trabajado 3 días distintos (lunes, martes, miércoles), el violín / consulta devuelve 4(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'friday', 'friday');
1 2 'monday' 'tuesday'
al1 2 'monday' 'wednesday'
resultado, aún debe ser de 4 días, pero devuelve 5Respuestas:
Básicamente, necesita encontrar la intersección de los días trabajados por cada uno
emp_id
en cada unotask
con todos los días de la semana, y luego contar los días distintos:Salida:
Demostración en SQLFiddle
fuente
join
conbetween
la condición logra el mismo resultado con mayor facilidad ...Un posible enfoque para simplificar el enunciado en la pregunta (violín) es utilizar el
VALUES
constructor de valores de tabla y las uniones apropiadas:Pero si desea contar los días distintos , la declaración es diferente. Es necesario encontrar todos los días entre el
start_day
y elend_day
rango y contar los días distintos:fuente
1 2 'monday' 'tuesday'
al1 2 'monday' 'wednesday'
resultado aún debe ser de 4 días, pero devuelve 5.monday
ywednesday
. ¿Me estoy perdiendo de algo?5
, no4
. Esta respuesta solo sugiere una declaración más simple. Gracias.Su consulta no es correcta Intente de lunes a martes con miércoles a jueves. Esto debería resultar en 4 días, pero su consulta devuelve 2 días. Su consulta ni siquiera detecta si dos rangos son adyacentes o se superponen o tampoco.
Una forma de resolver esto es escribir un CTE recursivo para obtener todos los días de un rango y luego contar días distintos.
Demostración: http://sqlfiddle.com/#!18/4a5ac/16
(Como se puede ver, no pude aplicar el constructor de valores directamente como en
with weekdays (day_name, day_number) as (values ('monday', 1), ...)
. No sé por qué. ¿Ese es SQL Server o yo? Bueno, con la selección adicional funciona :-)fuente
fuente
fuente