Desejo escrever uma consulta SQL para encontrar o número de dias úteis exclusivos para cada funcionário da tabela 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' |
*---------------------------------------*
Saída esperada:
*-------------------*
|emp_id no_of_days |
*-------------------*
| 1 4 |
| 2 5 |
*-------------------*
Eu escrevi a consulta sqlfiddle que está me dando a expected
saída, mas por curiosidade, existe uma maneira melhor de escrever esta consulta? Posso usar a mesa do calendário ou da tabela?
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
Qualquer sugestão seria ótima.
sql
sql-server
zeloso
fonte
fonte
(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'monday', 'tuesday');
empid_1 trabalhou 3 dias distintos (segunda-feira, terça-feira, quarta-feira), o violino / consulta retorna 4(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'friday', 'friday');
1 2 'monday' 'tuesday'
para1 2 'monday' 'wednesday'
o resultado ainda deve ser de 4 dias, mas retorna 5Respostas:
Você precisa basicamente encontrar a interseção dos dias trabalhados por cada
emp_id
umtask
com todos os dias da semana e depois contar os dias distintos:Resultado:
Demonstração no SQLFiddle
fonte
join
combetween
a condição de obter o mesmo resultado mais facilmente ...Uma abordagem possível para simplificar a declaração na pergunta (violino) é usar o
VALUES
construtor de valor de tabela e as junções apropriadas:Mas se você deseja contar os dias distintos , a declaração é diferente. Você precisa encontrar todos os dias entre a
start_day
eend_day
gama e conta as distintas dias:fonte
1 2 'monday' 'tuesday'
para1 2 'monday' 'wednesday'
o resultado ainda deve ser de 4 dias, mas retorna 5.monday
ewednesday
. Estou esquecendo de algo?5
, não4
. Esta resposta apenas sugere uma declaração mais simples. Obrigado.Sua consulta não está correta. Tente de segunda a terça-feira com quarta a quinta-feira. Isso deve resultar em 4 dias, mas sua consulta retorna 2 dias. Sua consulta nem detecta se dois intervalos são adjacentes ou sobrepostos ou nenhum.
Uma maneira de resolver isso é escrever uma CTE recursiva para obter todos os dias de um intervalo e depois contar dias distintos.
Demonstração: http://sqlfiddle.com/#!18/4a5ac/16
(Como pode ser visto, não pude aplicar o construtor de valores diretamente como em
with weekdays (day_name, day_number) as (values ('monday', 1), ...)
. Não sei por que. Esse é o SQL Server ou eu? Bem, com a seleção adicional funciona :-)fonte
fonte
fonte