Я хочу написать запрос SQL, чтобы найти количество уникальных рабочих дней для каждого сотрудника из таблицы 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' |
*---------------------------------------*
Ожидаемый результат:
*-------------------*
|emp_id no_of_days |
*-------------------*
| 1 4 |
| 2 5 |
*-------------------*
Я написал запрос sqlfiddle, который дает мне expected
вывод, но для любопытства есть лучший способ написать этот запрос? Могу ли я использовать Calender или Tally Table?
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
Любые предложения будут великолепны.
sql
sql-server
ревностный
источник
источник
(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'monday', 'tuesday');
empid_1 работал 3 разных дня (понедельник, вторник, среда), скрипта / запрос возвращает 4(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'friday', 'friday');
1 2 'monday' 'tuesday'
в1 2 'monday' 'wednesday'
результате все равно должны быть 4 дня , но она возвращает 5Ответы:
Вам нужно в основном найти пересечение дней, отработанных каждым
emp_id
из них,task
со всеми днями недели, а затем сосчитать различные дни:Вывод:
Демо на SQLFiddle
источник
join
сbetween
помощью условия в качестве условия легче достичь того же результата ...Один из возможных подходов к упрощению утверждения в вопросе (fiddle) заключается в использовании
VALUES
конструктора табличных значений и соответствующих объединений:Но если вы хотите посчитать разные дни, утверждение будет другим. Вам нужно найти все дни между
start_day
иend_day
диапазон и отсчитывать различные дни:источник
1 2 'monday' 'tuesday'
в1 2 'monday' 'wednesday'
результате все равно должны быть 4 дня , но он возвращает 5.monday
иwednesday
. Я что-то пропустил?5
, а не4
. Этот ответ просто предлагает более простое утверждение. Спасибо.Ваш запрос не верный. Попробуйте с понедельника по вторник со среды по четверг. Это должно привести к 4 дням, но ваш запрос вернет 2 дня. Ваш запрос даже не определяет, являются ли два диапазона смежными или перекрываются, или нет.
Один из способов решить эту проблему - написать рекурсивный CTE, чтобы получить все дни из диапазона, а затем подсчитать разные дни.
Демо-версия: http://sqlfiddle.com/#!18/4a5ac/16
(Как видно, я не мог применить конструктор значений напрямую, как в
with weekdays (day_name, day_number) as (values ('monday', 1), ...)
. Я не знаю почему. Это SQL Server или я? Ну, с дополнительным выбором это работает :-)источник
источник
источник