Fórum Aniversariantes da semana na Query #598331
31/10/2018
0
Contudo, a consulta não consigo fazer funcionar. Fiz assim:
Adoquery1.Close;
Adoquery1.SQL.Clear;
Adoquery1.SQL.Add('Select * from CadPessoas');
AdoQuery1.SQL.Add('Where (Extract(Month from CadPessoas.DtNasc) between Month(:DtNascIni) and Mont(:DtNascFim))and(Extract(day from CadPessoas.DtNasc) between day(:DtNascIni) and day(:DtNascFim))');
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := DateTimePicker1.DateTime;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := DateTimePicker2.DateTime;
AdoQuery1.Open;
Mas ele retorna "Objeto Parameter definido incorretamente. As informações são inconsistentes ou incompletas".
Alguém pode dar uma força?
Edilson Santiago
Curtir tópico
+ 0Post mais votado
31/10/2018
Experimente utilizar:
SELECT * FROM CadPessoas WHERE (DtNasc >= :DtNascFim) AND (DtNasc <= :DtNascIni)
Jerson Boer
Gostei + 2
Mais Posts
31/10/2018
Natanael Ferreira
http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini
Gostei + 0
31/10/2018
Edilson Santiago
Gostei + 0
31/10/2018
Edilson Santiago
http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini
Esse tópico é meu mesmo, de alguns anos atrás. Eu havia abandonado o projeto, e agora resolvi retomar com algumas alterações. O problema é que da forma como está naquele tópico, ele confunde mês 1 com mês 10,11 e 12. Ou seja, só seleciona corretamente os aniversariantes se os meses forem de 2 a 9. Em outubro, por exemplo, que é o mês 10, ele seleciona do mes 10, 11, 12 e 1.
Gostei + 0
31/10/2018
Jerson Boer
Select * from CadPessoas where (MONTH(DtNasc) between MONTH(:DtNascIni) AND MONTH(:DtNascFim)) AND (DAY(DtNasc) between DAY(:DtNascIni) and DAY(:DtNascFim))
Gostei + 1
01/11/2018
Emerson Nascimento
Select * from CadPessoas where MONTH(DtNasc) = :MesAtual AND DAY(DtNasc) between :DiaInicial and :DiaFinal
Como você não informou o banco de dados, posso te dar uma sugestão, de modo que a consulta fique dinâmica, sem a necessidade de passagem de parâmetros.
No SQL Sever:
Select * from CadPessoas where (MONTH(DtNasc) = Month(GetDate()) AND (DATEPART(wk,DtNasc) = DATEPART(wk,GETDATE()))
e no Firebird:
Select * from CadPessoas where (EXTRACT(MONTH FROM DtNasc) = EXTRACT(MONTH FROM CURRENT_DATE)) AND EXTRACT(DAY FROM DtNasc) BETWEEN ( EXTRACT(DAY FROM DtNasc) - EXTRACT(WEEKDAY FROM DtNasc) ) AND ( EXTRACT(DAY FROM DtNasc) [sinaldemais] (6 - EXTRACT(WEEKDAY FROM DtNasc)) )
Gostei + 1
03/11/2018
Edilson Santiago
Select * from CadPessoas where MONTH(DtNasc) = :MesAtual AND DAY(DtNasc) between :DiaInicial and :DiaFinal
Como você não informou o banco de dados, posso te dar uma sugestão, de modo que a consulta fique dinâmica, sem a necessidade de passagem de parâmetros.
No SQL Sever:
Select * from CadPessoas where (MONTH(DtNasc) = Month(GetDate()) AND (DATEPART(wk,DtNasc) = DATEPART(wk,GETDATE()))
e no Firebird:
Select * from CadPessoas where (EXTRACT(MONTH FROM DtNasc) = EXTRACT(MONTH FROM CURRENT_DATE)) AND EXTRACT(DAY FROM DtNasc) BETWEEN ( EXTRACT(DAY FROM DtNasc) - EXTRACT(WEEKDAY FROM DtNasc) ) AND ( EXTRACT(DAY FROM DtNasc) [sinaldemais] (6 - EXTRACT(WEEKDAY FROM DtNasc)) )
Olá, Emerson, como o projeto é pequeno, e terá poucos registros, estou utilizando Access mesmo, com conexão ADO
Gostei + 0
03/11/2018
Edilson Santiago
//Realiza a consulta
Adoquery1.Close;
Adoquery1.SQL.Clear;
Adoquery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where ((Month(DtNasc) * 100) + Day(DtNasc)) between :DtNascIni and :DtNascFim');
AdoQuery1.SQL.add('Order by DtNasc');
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := MonthOf(DateTimePicker1.DateTime) * 100 + DayOf(DateTimePicker1.DateTime);
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := MonthOf(DateTimePicker2.DateTime)*100 + DayOf(DateTimePicker2.DateTime);
AdoQuery1.Open;Contudo, quando consulto os aniversários entre 01/01 e 01/02, ele retorna todos nascidos em 01/10, 01/11, 01/12 e 01/01. Ou seja, parece que está confundindo os meses que tem 1 (01, 10, 11 e 12).
Gostei + 0
05/11/2018
Emerson Nascimento
//Realiza a consulta
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where ((Month(DtNasc) * 100) [sinaldemais] Day(DtNasc)) between :DtNascIni and :DtNascFim');
ADOQuery1.SQL.add('Order by DtNasc');
ADOQuery1.Parameters.ParamByName('DtNascIni').AsInteger := (MonthOf(DateTimePicker1.DateTime)*100) [sinaldemais] DayOf(DateTimePicker1.DateTime);
ADOQuery1.Parameters.ParamByName('DtNascFim').AsInteger := (MonthOf(DateTimePicker2.DateTime)*100) [sinaldemais] DayOf(DateTimePicker2.DateTime);
ADOQuery1.Open;As únicas alterações em comparação com a tua postagem estão na passagem dos parâmetros, onde eu forço a tipagem do parâmetro (AsInteger), e também coloquei os parênteses na multiplicação do mês.
Mas, pelo meu entendimento, a instrução deveria ter funcionado.
Gostei + 1
05/11/2018
Edilson Santiago
<br />
[Error] unit_aniversarios.pas(104): Undeclared identifier: ''AsInteger''
Gostei + 0
05/11/2018
Edilson Santiago
Acontece que os meses são salvos no access com dois dígitos cada, logo, janeiro é 01, fevereiro, 02, etc.
Acontece que, quando extraio o mês do datetimepicker, se ele for entre janeiro e setembro, ele extrai com um dígito só, tipo, janeiro = 1, fevereiro =2, etc.
Aí, quando a consulta busca duas datas entre o mês de janeiro, por exemplo, ele considera todos os meses que tem 1 na sua composição, ou seja, 1, 10, 11 e 12. Logo, só lê o primeiro dígito, e interpreta todos esses meses como mês 1.
Agora, como faço para resolver isso?
Gostei + 0
05/11/2018
Edilson Santiago
Gostei + 0
05/11/2018
Emerson Nascimento
Não faz sentido, visto que a função Month() retorna um valor numérico. Logo, 1o de janeiro, aplicando a fórmula que você fez, resultará em 101 (mes * 100, mais dia).
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where cint((Month(DtNasc) * 100) [sinaldemais] Day(DtNasc)) between :DtNascIni and :DtNascFim');
ADOQuery1.SQL.add('Order by DtNasc');
ADOQuery1.Parameters.ParamByName('DtNascIni').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := (MonthOf(DateTimePicker1.DateTime)*100) [sinaldemais] DayOf(DateTimePicker1.DateTime);
ADOQuery1.Parameters.ParamByName('DtNascFim').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := (MonthOf(DateTimePicker2.DateTime)*100) [sinaldemais] DayOf(DateTimePicker2.DateTime);
ADOQuery1.Open;
Gostei + 1
05/11/2018
Emerson Nascimento
Gostei + 1
05/11/2018
Edilson Santiago
Ele pega mês vezes 100 mais dia, tanto na data inicial quanto na final, certo? Então para 25/12, que é a data inicial, ele resulta em 1200 + 25 = 1225. A data final que é 05/01 ele resulta em 100 + 5 = 105. Como não há uma especificação de limite nem de ordem, se é crescente ou decrescente, ele ta pegando de trás pra frente, entre a última e a primeira.
Assim, penso que só conseguiria resolver com uma cláusula if dentro do sql, se é que isso é possível. Algo mais ou menos assim:
if month(DtNascIni) > month(DtNascFim) then
ADOQuery1.SQL.add('where cint((Month(DtNasc) * 100) + Day(DtNasc)) between (:DtNascIni and 1231) and ((Month(DtNasc) * 100) + Day(DtNasc)) between (101 and :DtNascFim));
porém com a codificação correta. Nesse caso, se o mês final for menor que o mês inicial, que é o caso da virada, ele faria duas consultas. A data inicial até 31/12 e a segunda consulta seria de 01/01 até a data final.
Na minha consulta entre 25/12 e 05/01, nesse caso, ele faria uma consulta entre 1225 a 1231 e outra consulta entre 101 a 105 e exibiria as duas consultas no dbgrid.
Será que isso é possível?
Gostei + 0
06/11/2018
Emerson Nascimento
"Gambiarra", mas....
intMesDiaIni := (MonthOf(DateTimePicker1.DateTime)*100) + DayOf(DateTimePicker1.DateTime);
intMesDiaFim := (MonthOf(DateTimePicker2.DateTime)*100) + DayOf(DateTimePicker2.DateTime);
intMesDiaIni2 := intMesDiaIni;
intMesDiaFim2 := intMesDiaFim;
if intMesDiaIni > intMesDiaFim then
begin
intMesDiaFim := 1231; // 31 de dezembro
intMesDiaIni2 := 101; // 1o de janeiro
end;
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where (cint((Month(DtNasc) * 100) + Day(DtNasc)) between :DtNascIni and :DtNascFim)');
ADOQuery1.SQL.add('or (cint((Month(DtNasc) * 100) + Day(DtNasc)) between :DtNascIni2 and :DtNascFim2)');
ADOQuery1.SQL.add('Order by DtNasc');
ADOQuery1.Parameters.ParamByName('DtNascIni').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := intMesDiaIni;
ADOQuery1.Parameters.ParamByName('DtNascFim').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := intMesDiaFim;
ADOQuery1.Parameters.ParamByName('DtNascIni2').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni2').Value := intMesDiaIni2;
ADOQuery1.Parameters.ParamByName('DtNascFim2').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim2').Value := intMesDiaFim2;
ADOQuery1.Open;
Gostei + 1
Clique aqui para fazer login e interagir na Comunidade :)