Aniversariantes da semana na Query
Boa tarde. Preciso de uma query que me retorne em um dbgrid os aniversariantes da semana. Fiz uma rotina no onshow do formulário onde um datetimepicker1 recebe sempre o domingo anterior à data atual, e o datetimepicker2 recebe sempre o sábado posterior à data atual. Assim, quando abro o form, o intervalo já fica automático. Essa parte funcionou.
Contudo, a consulta não consigo fazer funcionar. Fiz assim:
Mas ele retorna "Objeto Parameter definido incorretamente. As informações são inconsistentes ou incompletas".
Alguém pode dar uma força?
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
Curtidas 0
Melhor post
Jerson Boer
31/10/2018
Olá Edilson, se você está fazendo a busca entre 2 datas, por qual razão está utilizando a captura do mês e dia ao invés da busca simples entre 2 datas?
Experimente utilizar:
Experimente utilizar:
SELECT * FROM CadPessoas WHERE (DtNasc >= :DtNascFim) AND (DtNasc <= :DtNascIni)
GOSTEI 2
Mais Respostas
Natanael Ferreira
31/10/2018
Veja se este tópico ajuda:
http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini
http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini
GOSTEI 0
Edilson Santiago
31/10/2018
O problema é que não pode ser captura entre duas datas, pois senão teria que definir o ano também. como estou buscando os aniversariantes da semana, teria que retornar, por exemplo, os nascidos em 30/10/2000 e também os nascidos em 30/10/1930. Logo tenho que ignorar o ano, e buscar só dia e mês.
GOSTEI 0
Edilson Santiago
31/10/2018
Veja se este tópico ajuda:
http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini
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
Jerson Boer
31/10/2018
Está correto, não me atentei que no caso o ano deveria ser desconsiderado, veja se assim faz algum sentido:
Select * from CadPessoas where (MONTH(DtNasc) between MONTH(:DtNascIni) AND MONTH(:DtNascFim)) AND (DAY(DtNasc) between DAY(:DtNascIni) and DAY(:DtNascFim))
GOSTEI 1
Emerson Nascimento
31/10/2018
precisa ser algo assim:
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:
e no Firebird:
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
Edilson Santiago
31/10/2018
precisa ser algo assim:
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:
e no Firebird:
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
Edilson Santiago
31/10/2018
Então, eu tentei também utilizar o código do projeto antigo. Ficou assim:
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).
//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
Emerson Nascimento
31/10/2018
Tente assim:
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.
//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
Edilson Santiago
31/10/2018
Não roda. Dá o seguinte erro:<br />
<br />
[Error] unit_aniversarios.pas(104): Undeclared identifier: ''AsInteger''
<br />
[Error] unit_aniversarios.pas(104): Undeclared identifier: ''AsInteger''
GOSTEI 0
Edilson Santiago
31/10/2018
Acho que descobri o problema, mas não sei como resolver.
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?
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
Edilson Santiago
31/10/2018
Alterei o formato do mês no banco de dados, mas também não resolveu. Estou ficando louco aqui, rsrsrs
GOSTEI 0
Emerson Nascimento
31/10/2018
Acontece que os meses são salvos no access com dois dígitos cada, logo, janeiro é 01, fevereiro, 02, etc.
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
Emerson Nascimento
31/10/2018
veja que no último exemplo, ainda dentro do access, transformo o resultado do campo em inteiro, pra depois compara com os inteiros passados nos parâmetros.
GOSTEI 1
Edilson Santiago
31/10/2018
Dessa forma resolveu o problema em parte. Agora ele só ta bugando se tiver virada de ano no intervalo. Por exemplo, consultei entre 25/12 e 05/01 e ele retornou mes 09, 10, 11 e 12. Analisando o cálculo na marreta, o que acontece?
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?
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
Emerson Nascimento
31/10/2018
Resolva no Delphi.
"Gambiarra", mas....
"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
Edilson Santiago
31/10/2018
Graças a Deus, e à enorme ajuda do Emerson, resolvido. Com todas as dicas, ficou assim o código final:
Muito obrigado mesmo. Vou marcar como resolvido e acho que esse tópico vai ajudar muita gente, pq vi muitas perguntas semelhantes e sem solução na internet.
Até a próxima. Vlw!
if monthOf(Datetimepicker1.DateTime) <= monthOf(Datetimepicker2.DateTime) then
begin
//Realiza a consulta
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('Order by DtNasc');
ADOQuery1.Parameters.ParamByName('DtNascIni').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := (MonthOf(DateTimePicker1.DateTime)*100) + DayOf(DateTimePicker1.DateTime);
ADOQuery1.Parameters.ParamByName('DtNascFim').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := (MonthOf(DateTimePicker2.DateTime)*100) + DayOf(DateTimePicker2.DateTime);
ADOQuery1.Open;
end
else
begin
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 := (MonthOf(DateTimePicker1.DateTime)*100) + DayOf(DateTimePicker1.DateTime);
ADOQuery1.Parameters.ParamByName('DtNascFim').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := 1231;
ADOQuery1.Parameters.ParamByName('DtNascIni2').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni2').Value := 101;
ADOQuery1.Parameters.ParamByName('DtNascFim2').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim2').Value := (MonthOf(DateTimePicker2.DateTime)*100) + DayOf(DateTimePicker2.DateTime);
AdoQuery1.Open;
end;Muito obrigado mesmo. Vou marcar como resolvido e acho que esse tópico vai ajudar muita gente, pq vi muitas perguntas semelhantes e sem solução na internet.
Até a próxima. Vlw!
GOSTEI 0
André Rufino
31/10/2018
Acabei de fazer assim e funcionou:
Dm.Consulta2.Close;
Dm.Consulta2.SQL.Clear;
Dm.Consulta2.SQL.Add(''Select RazSoc as Paciente, FonCli as Telefone, DatAni as Nascimento From Clientes '');
Dm.Consulta2.SQL.Add(''Where MONTH(DatAni)=:Mes and DAY(DatAni)=:Dia'');
Dm.Consulta2.ParamByName(''Mes'').asInteger:=iMes;
Dm.Consulta2.ParamByName(''Dia'').asInteger:=iDia;
Dm.Consulta2.Open;
Dm.Consulta2.First;
GOSTEI 0