Olá manusud,
Acho que existem diferentes soluções para seu problema. Vou postar aqui uma solução que TALVEZ resolva seu problema, mas tenho certeza que os foristas dispõe de outras sugestões, talvez mais fáceis que a minha:
Primeiro, vamos montar uma querie que indica se uma venda não se encaixa nos horarios liberados para a filial:
Selecionar tudo
-- Esta querie bate as vendas com os horarios permitidos
-- Se um deles estiver dentro das horas autorizadas, marca autorizado como "S"
SELECT V.NUMERO_FILIAL,
V.DATA_HORA_VENDA,
H.DT_HR_INICIO,
H.DT_HR_FIM,
CASE WHEN V.DATA_HORA_VENDA NOT BETWEEN H.DT_HR_INICIO AND H.DT_HR_FIM
THEN 'N'
ELSE 'S' END AS AUTORIZADO
FROM VENDA V,
HORARIO_AUTORIZADO H
WHERE V.NUMERO_FILIAL = H.NUMERO_FILIAL
A querie acima faz um produto cartesiano entre VENDAS e os HORARIOS AUTORIZADOS de uma mesma filial. Ela parece uma "querie burra", pois um "dia/hora venda" será comparado com vários "dias/horas autorizados". Pode ser que esta venda se encaixe em um dos horarios autorizados ou em nenhum deles. Mas vamos deixar ela como está, pois depois a usaremos em outra querie maior. Se a venda se encaixa em algum horario permitido, então marcará uma coluna AUTORIZADO com "SIM". Caso contrário, com "não"
Agora, vamos passar um filtro nesta queire, para que ele nos retorne somente as vendas autorizadas, ou seja, somente as vendas de uma filial que estejam em um dos intervalos permitidos. Se alguma venda foi feita em horario não permitido, ela não aparecera aqui.
Selecionar tudo
-- Esta querie filtra todos os horarios de venda permitidos
-- Uma venda de filial que não se encaixe em um periodo permitido não será mostrada aqui
SELECT Z.NUMERO_FILIAL,
Z.DATA_HORA_VENDA
FROM (-- Esta querie bate as vendas com os horarios permitidos
-- Se um deles estiver dentro das horas autorizadas, marca autorizado como "S"
SELECT V.NUMERO_FILIAL,
V.DATA_HORA_VENDA,
H.DT_HR_INICIO,
H.DT_HR_FIM,
CASE WHEN V.DATA_HORA_VENDA NOT BETWEEN H.DT_HR_INICIO AND H.DT_HR_FIM
THEN 'N' ELSE 'S' END AS AUTORIZADO
FROM VENDA V,
HORARIO_AUTORIZADO H
WHERE V.NUMERO_FILIAL = H.NUMERO_FILIAL
) Z
WHERE Z.AUTORIZADO = 'S'
E agora, vamos montar a querie mais simples de todas, que mostra TODAS as vendas ocorridas
Selecionar tudo
-- Esta querie relaciona todas as vendas, autorizadas ou não
SELECT V.NUMERO_FILIAL,
V.DATA_HORA_VENDA
FROM VENDA
Pronto .. temos todas as informações que precisamos: "todas as vendas das filiais" e "vendas autorizadas das filiais".
Se subtrairmos as "vendas autorizadas" das "vendas totais", chegaremos nas "vendas irregulares". Para isso uso a função MINUS e construo a querie final:
Selecionar tudo
-- Esta querie mostra somente as vendas irregulares
SELECT W.NUMERO_FILIAL
W.DATA_HORA_VENDA
FROM
(
-- Esta querie relaciona todas as vendas, autorizadas ou não
SELECT V.NUMERO_FILIAL,
V.DATA_HORA_VENDA
FROM VENDA
MINUS
-- Esta querie filtra todos os horarios de venda permitidos
-- Uma venda de filial que não se encaixe em um periodo permitido não será mostrada aqui
SELECT Z.NUMERO_FILIAL,
Z.DATA_HORA_VENDA
FROM (-- Esta querie bate as vendas com os horarios permitidos
-- Se um deles estiver dentro das horas autorizadas, marca autorizado como "S"
SELECT V.NUMERO_FILIAL,
V.DATA_HORA_VENDA,
H.DT_HR_INICIO,
H.DT_HR_FIM,
CASE WHEN V.DATA_HORA_VENDA NOT BETWEEN H.DT_HR_INICIO AND H.DT_HR_FIM
THEN 'N' ELSE 'S' END AS AUTORIZADO
FROM VENDA V,
HORARIO_AUTORIZADO H
WHERE V.NUMERO_FILIAL = H.NUMERO_FILIAL
) Z
WHERE Z.AUTORIZADO = 'S'
) W
Não tenho como garantir que a querie acima está 100% certa. Você precisaria testar em sua massa de dados.
Talvez os foristas tenham outras sugestões bem mais simples do que a minha.
Abraços,
Sergio Coutinho