I want the query to return the days unfilled by users, disregarding Saturdays and Sundays,
Jorge, the suggestion is that you store in the Preenchimento
table only the events that occurred and that at the time the query is executed, the workday table for the period is set.
For example:
-- código #1
declare @DataInicial date, @DataFinal date;
set dateformat dmy;
-- informe as datas no formato dd/mm/aaaa
set @DataInicial= cast('5/9/2018' as date);
set @DataFinal= cast('20/9/2018' as date);
--
set datefirst 1; -- semana inicia na segunda-feira
with
Datas as (
SELECT @DataInicial as Dia
union all
SELECT dateadd(day, +1, Dia)
from Datas
where Dia < @DataFinal
),
DxU as (
SELECT U.Vendedor, D.Dia
from Datas as D
cross join Usuário as U
where datepart(dw, D.Dia) <= 5
-- and Dia não é feriado
)
SELECT DU.Vendedor, DU.Dia
from DxU as DU
where not exists (SELECT *
from Preenchimento as P
where P.Dia = DU.Dia
and P.Vendedor = DU.Vendedor);
To facilitate the understanding and maintenance of the code, common table expressions (CTE) were used to implement modular programming, as described in the article "Modular Programming with Table Expressions (CTE)", published in the section " Articles " from Porto SQL .
CTE Datas
generates the days in the period. You can follow this by isolating the first part of code # 1:
-- código #1 parte 1
declare @DataInicial date, @DataFinal date;
set dateformat dmy;
-- informe as datas no formato dd/mm/aaaa
set @DataInicial= cast('5/9/2018' as date);
set @DataFinal= cast('20/9/2018' as date);
--
with
Datas as (
SELECT @DataInicial as Dia
union all
SELECT dateadd(day, +1, Dia)
from Datas
where Dia < @DataFinal
)
SELECT Dia
from Datas;
The second CTE, DxU
, filters the dates to keep only from Monday to Friday in the CTE and also realizes the Cartesian product with the table of existing users.
-- código #1 parte 2
declare @DataInicial date, @DataFinal date;
set dateformat dmy;
-- informe as datas no formato dd/mm/aaaa
set @DataInicial= cast('5/9/2018' as date);
set @DataFinal= cast('20/9/2018' as date);
--
set datefirst 1; -- semana inicia na segunda-feira
with
Datas as (
SELECT @DataInicial as Dia
union all
SELECT dateadd(day, +1, Dia)
from Datas
where Dia < @DataFinal
),
DxU as (
SELECT U.Vendedor, D.Dia
from Datas as D
cross join Usuário as U
where datepart(dw, D.Dia) <= 5
-- and Dia não é feriado
)
SELECT Vendedor, Dia
from DxU;
Please note that if you want working days you will also need a holiday table (local, state and national).
I did not test the code; may contain error (s).