Chcę napisać zapytanie SQL, aby znaleźć liczbę unikalnych dni roboczych dla każdego pracownika z tabeli 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' |
*---------------------------------------*
Oczekiwany wynik:
*-------------------*
|emp_id no_of_days |
*-------------------*
| 1 4 |
| 2 5 |
*-------------------*
Napisałem zapytanie sqlfiddle, które daje mi expected
wynik, ale dla ciekawości jest lepszy sposób na napisanie tego zapytania? Czy mogę korzystać z kalendarza lub tabeli Tally?
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
Wszelkie sugestie byłyby świetne.
sql
sql-server
gorliwy
źródło
źródło
(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'monday', 'tuesday');
empid_1 pracował 3 różne dni (poniedziałek, wtorek, środa), skrzypce / zapytanie zwraca 4(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'friday', 'friday');
1 2 'monday' 'tuesday'
się1 2 'monday' 'wednesday'
wynik powinien być jeszcze 4 dni ale zwraca 5Odpowiedzi:
Musisz po prostu znaleźć przecięcie dni przepracowanych przez każdy
emp_id
z nichtask
we wszystkie dni tygodnia, a następnie policzyć poszczególne dni:Wynik:
Demo na SQLFiddle
źródło
join
pomocąbetween
as, ponieważ warunek łatwiej osiąga ten sam wynik ...Jednym z możliwych sposobów uproszczenia instrukcji w pytaniu (skrzypce) jest użycie
VALUES
konstruktora wartości tabeli i odpowiednich połączeń:Ale jeśli chcesz policzyć różne dni, oświadczenie jest inne. Musisz znaleźć wszystkie dni od
start_day
i doend_day
zakresu i policzyć poszczególne dni:źródło
1 2 'monday' 'tuesday'
się1 2 'monday' 'wednesday'
wynik powinien być jeszcze 4 dni ale zwraca 5.monday
iwednesday
. Czy coś brakuje?5
, nie4
. Ta odpowiedź sugeruje prostsze stwierdzenie. Dzięki.Twoje zapytanie jest nieprawidłowe Spróbuj od poniedziałku do wtorku od środy do czwartku. Powinno to dać 4 dni, ale zapytanie zwraca 2 dni. Twoje zapytanie nawet nie wykrywa, czy dwa zakresy sąsiadują ze sobą, czy się pokrywają, czy też nie.
Jednym ze sposobów rozwiązania tego jest napisanie rekurencyjnego CTE, aby uzyskać wszystkie dni z zakresu, a następnie policzyć różne dni.
Demo: http://sqlfiddle.com/#!18/4a5ac/16
(Jak widać, nie mogłem zastosować konstruktora wartości bezpośrednio jak w
with weekdays (day_name, day_number) as (values ('monday', 1), ...)
. Nie wiem dlaczego. Czy to SQL Server czy ja? Cóż, przy dodatkowym zaznaczeniu działa :-)źródło
źródło
źródło