Je souhaite écrire une requête SQL pour trouver le nombre de jours ouvrables uniques pour chaque employé de la table 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' |
*---------------------------------------*
Production attendue:
*-------------------*
|emp_id no_of_days |
*-------------------*
| 1 4 |
| 2 5 |
*-------------------*
J'ai écrit la requête sqlfiddle qui me donne la expected
sortie mais par curiosité existe-t-il une meilleure façon d'écrire cette requête? Puis-je utiliser la table Calendrier ou 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
Toute suggestion sera appréciée.
sql
sql-server
zélé
la source
la source
(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'monday', 'tuesday');
empid_1 a fonctionné 3 jours distincts (lundi, mardi, mercredi), le violon / requête renvoie 4(1, 1, 'monday', 'wednesday'),(1, 2, 'monday', 'tuesday'),(1, 3, 'friday', 'friday');
1 2 'monday' 'tuesday'
pour1 2 'monday' 'wednesday'
le résultat devrait toujours être de 4 jours mais il retourne 5Réponses:
Vous devez essentiellement trouver l'intersection des jours travaillés par chacun
emp_id
sur chacuntask
avec tous les jours de la semaine, puis compter les jours distincts:Production:
Démo sur SQLFiddle
la source
join
avecbetween
car la condition obtient plus facilement le même résultat ...Une approche possible pour simplifier l'énoncé de la question (violon) consiste à utiliser
VALUES
le constructeur de valeur de table et les jointures appropriées:Mais si vous voulez compter les jours distincts , la déclaration est différente. Vous devez trouver tous les jours entre la
start_day
etend_day
portée et compter les jours distincts:la source
1 2 'monday' 'tuesday'
au1 2 'monday' 'wednesday'
résultat devrait toujours être de 4 jours mais il retourne 5.monday
etwednesday
. Suis-je en train de manquer quelque chose?5
non4
. Cette réponse suggère simplement une déclaration plus simple. Merci.Votre requête n'est pas correcte. Essayez du lundi au mardi et du mercredi au jeudi. Cela devrait aboutir à 4 jours, mais votre requête renvoie 2 jours. Votre requête ne détecte même pas si deux plages sont adjacentes ou se chevauchent ou aucune.
Une façon de résoudre ce problème consiste à écrire un CTE récursif pour obtenir tous les jours d'une plage, puis compter les jours distincts.
Démo: http://sqlfiddle.com/#!18/4a5ac/16
(Comme on peut le voir, je ne pouvais pas appliquer le constructeur de valeurs directement comme dans
with weekdays (day_name, day_number) as (values ('monday', 1), ...)
. Je ne sais pas pourquoi. Est-ce SQL Server ou moi? Eh bien, avec la sélection supplémentaire, cela fonctionne :-)la source
la source
la source