Select entre 3 tabelas
Boa noite, estou com a seguinte estrutura no banco de dados:
E usando esta instrução para consulta:
Nas tabelas tenho 2 Medicos, 2 Clientes e 2 consultas para cada medico. Teoricamente na consulta deveria me retornar 4 registros da tabela AGENDA_MEDICO, mas está me retornando 8 registros.
Alguém poderia dar uma ajuda e uma melhorada nesta instrução?
Desde já meu muito obrigado pela atenção.
CREATE TABLE AGENDA_MEDICO (
AGM_CODIGO INTEGER NOT NULL,
AGM_CODIGOMED INTEGER,
AGM_CODIGOCLI INTEGER,
AGM_DIA DATE,
AGM_HORA TIME
);
CREATE TABLE CLIENTES (
CLI_CODIGO INTEGER NOT NULL,
CLI_NOME VARCHAR(60),
CLI_TELEFONE VARCHAR(12),
CLI_CELULAR VARCHAR(12)
);
CREATE TABLE MEDICOS (
MED_CODIGO INTEGER NOT NULL,
MED_NOME VARCHAR(60)
);
E usando esta instrução para consulta:
SELECT A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA, M.MED_CODIGO, M.MED_NOME, C.CLI_CODIGO, C.CLI_NOME FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C WHERE A.AGM_CODIGOMED = M.MED_CODIGO
Nas tabelas tenho 2 Medicos, 2 Clientes e 2 consultas para cada medico. Teoricamente na consulta deveria me retornar 4 registros da tabela AGENDA_MEDICO, mas está me retornando 8 registros.
Alguém poderia dar uma ajuda e uma melhorada nesta instrução?
Desde já meu muito obrigado pela atenção.
Jiraya San
Curtidas 0
Melhor post
Randrade
25/11/2014
Bom, posso estar enganado, mas você não está passando o código do cliente para verificar, assim o banco está trazendo seus dados de cada médico e cada cliente, totalizando 8.
Tente colocar a condição do cliente junto no seu select.
Testei aqui e me retornou apenas os 4 registros, não sei se era isso que vc queria.
Qualquer coisa avise.
Tente colocar a condição do cliente junto no seu select.
Testei aqui e me retornou apenas os 4 registros, não sei se era isso que vc queria.
Qualquer coisa avise.
SELECT distinct A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA, M.MED_CODIGO, M.MED_NOME, C.CLI_CODIGO, C.CLI_NOME FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C WHERE A.AGM_CODIGOMED = M.MED_CODIGO AND A.AGM_CODIGOCLI = C.CLI_CODIGO;
GOSTEI 1
Mais Respostas
Jiraya San
25/11/2014
Opa Renilson rodei sua SQL aqui no IBExperte e me trouxe 4 registros. Amanhã vou tentar implementar ele na App.
Com relação ao código do médico para filtrar, vou estar pegando ele de um DBLouckpCombobox. Valeu, vou tentar e dou um retorno aqui.
Com relação ao código do médico para filtrar, vou estar pegando ele de um DBLouckpCombobox. Valeu, vou tentar e dou um retorno aqui.
GOSTEI 0
Randrade
25/11/2014
Ok, caso não funcione da maneira esperada, retorne que tentarei lhe ajudar.
GOSTEI 0
Jiraya San
25/11/2014
Boa tarde o SQL que você me passou funcionou no IBExpert e no Componente FDQuery.
Estou tentando agora ao clicar em um dia no TMonthCalendar e tendo um médico selecionado
no DBLookupComboBox ele me filtre os dados no DBGrid.
Modelo de tela:
[img]http://arquivo.devmedia.com.br/forum/imagem/390998-20141126-164408.jpg[/img]
Para efeito de teste coloquei a mesma Instrução SQL:
E me apresentou o seguinte erro:
Teria uma dica de como resolver?
Desde já obrigado pela atenção.
Estou tentando agora ao clicar em um dia no TMonthCalendar e tendo um médico selecionado
no DBLookupComboBox ele me filtre os dados no DBGrid.
Modelo de tela:
[img]http://arquivo.devmedia.com.br/forum/imagem/390998-20141126-164408.jpg[/img]
Para efeito de teste coloquei a mesma Instrução SQL:
with FDQryAgendaMedico do
begin
Close;
SQL.Add('SELECT distinct');
SQL.Add('A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA,');
SQL.Add('M.MED_CODIGO, M.MED_NOME,');
SQL.Add('C.CLI_CODIGO, C.CLI_NOME');
SQL.Add('FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C');
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
Open;
First;
end;
E me apresentou o seguinte erro:
[FireDac][Phys][FB]Dynamic SQL Error SQL error code = -104 Token unknown - line 8, column 1 SELECT.
Teria uma dica de como resolver?
Desde já obrigado pela atenção.
GOSTEI 0
Renato Rubinho
25/11/2014
Buenas,
Deve ser só dar um "SQL.Clear" após fechar a FDQryAgendaMedico e antes de preencher o comando novamente, porque da forma que está, se a FDQryAgendaMedico possuir já algum comando ou se for aberta mais de uma vez acontecerá o erro.
Abraççç,
rrubinho
Deve ser só dar um "SQL.Clear" após fechar a FDQryAgendaMedico e antes de preencher o comando novamente, porque da forma que está, se a FDQryAgendaMedico possuir já algum comando ou se for aberta mais de uma vez acontecerá o erro.
with FDQryAgendaMedico do
begin
Close;
SQL.Clear; // <<<<<<<<<<<------------
SQL.Add('SELECT distinct');
SQL.Add('A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA,');
SQL.Add('M.MED_CODIGO, M.MED_NOME,');
SQL.Add('C.CLI_CODIGO, C.CLI_NOME');
SQL.Add('FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C');
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
Open;
First;
end;
Abraççç,
rrubinho
GOSTEI 0
Jiraya San
25/11/2014
Opa bom dia a todos, rrubinho segui sua dica e funfou.
Estou tendo problemas para ao clicar em uma data no Calendário ou ao selecionar o Médico no ComboBox ele filtrar a agenda referente ao médico e dia.
SQL usada até o momento:
Só que está dando erro e não compila.
Não estou conseguindo fazer a conversão, ou minha lógica na String SQL está incorreta.
Se puderem ajudar, desde já agradeço.
Estou tendo problemas para ao clicar em uma data no Calendário ou ao selecionar o Médico no ComboBox ele filtrar a agenda referente ao médico e dia.
SQL usada até o momento:
procedure TFrmPrincipal.SelecionaMedico;
begin
with FDQryAgendaMedico do
begin
Close;
SQL.Clear;
SQL.Add('SELECT distinct');
SQL.Add('A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA,');
SQL.Add('M.MED_CODIGO, M.MED_NOME,');
SQL.Add('C.CLI_CODIGO, C.CLI_NOME, C.CLI_TELEFONE');
SQL.Add('FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C');
//SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO');
SQL.Add('AND ' + FDQryAgendaMedico.ParamByName('AGM_DIA').AsString = Calendar.Date);
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
SQL.Add('ORDER BY AGM_DIA, AGM_HORA');
Open;
First;
end;
end;
Só que está dando erro e não compila.
[dcc32 Error] uPrincipal.pas(300): E2010 Incompatible types: 'string' and 'TDate' [dcc32 Warning] uPrincipal.pas(300): W1058 Implicit string cast with potential data loss from 'string' to 'ShortString'
Não estou conseguindo fazer a conversão, ou minha lógica na String SQL está incorreta.
Se puderem ajudar, desde já agradeço.
GOSTEI 0
Renato Rubinho
25/11/2014
Buenas,
Tem uma confusãozinha no seu código... rsrs
1. Você comentou o "WHERE"
2. Neste trecho você não está filtrando nenhum campo do select
Opção 1: // Atribuindo diretamente o Valor
Opção 2: // Passando parâmetro :
Abraççç,
rrubinho
Tem uma confusãozinha no seu código... rsrs
1. Você comentou o "WHERE"
2. Neste trecho você não está filtrando nenhum campo do select
SQL.Add('AND ' + FDQryAgendaMedico.ParamByName('AGM_DIA').AsString = Calendar.Date);
// Se fosse uma "tradução" e tivesse selecionado o dia de hoje, seria
' AND '' = 28/11/2014 '
Opção 1: // Atribuindo diretamente o Valor
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO');
// Atribui o valor direto do campo
SQL.Add('AND A.AGM_DIA = ' + QuotedStr(FormatDateTime('dd.mm.yyyy',Calendar.Date)));
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
SQL.Add('ORDER BY AGM_DIA, AGM_HORA');
Open;
Opção 2: // Passando parâmetro :
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO');
// Atribui o valor de um parâmetro ao campo de data
SQL.Add('AND A.AGM_DIA = :W_AGM_DIA');
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
SQL.Add('ORDER BY AGM_DIA, AGM_HORA');
// Preenche o parâmetro antes do Open
FDQryAgendaMedico.Params.ParamByName('AGM_DIA').AsDateTime = Calendar.Date;
// Abre a query
Open;
Abraççç,
rrubinho
GOSTEI 0
Jiraya San
25/11/2014
Olá galera estive até agora quebrando a cuca, mas não consegui finalizar esta questão.
Minha tabela no banco:
[img]http://arquivo.devmedia.com.br/forum/imagem/390998-20141129-221933.jpg[/img]
Meu form:
[img]http://arquivo.devmedia.com.br/forum/imagem/390998-20141126-164408.jpg[/img]
Minha função para conultar a Agenda do dia trazendo a Data, Medico e Cliente.
1- Rodo a aplicação e escolho um médico no ComboBox, independente de qual médico eu escolha me traz a consulta do dia. Obs. coloquei para ele começar com a data de hoje Calendar.Date:= Now;
2- Troco de Médico, continua com o mesmo resultado da consulta anterior.
3- Clico em uma data do Calendário que tem consulta gravada no banco, ele me traz o registros cadastrado, mas não troca o Médico no ComboBox.
Alguém poderia dar uma luz? se preciso for mando esta parte que estou desenvolvendo por email. Desde já obrigado pela atenção.
Minha tabela no banco:
[img]http://arquivo.devmedia.com.br/forum/imagem/390998-20141129-221933.jpg[/img]
Meu form:
[img]http://arquivo.devmedia.com.br/forum/imagem/390998-20141126-164408.jpg[/img]
Minha função para conultar a Agenda do dia trazendo a Data, Medico e Cliente.
procedure TFrmPrincipal.SelecionaMedico;
begin
with FDQryAgendaMedico do
begin
Close;
SQL.Clear;
SQL.Add('SELECT distinct');
SQL.Add('A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA,');
SQL.Add('M.MED_CODIGO, M.MED_NOME,');
SQL.Add('C.CLI_CODIGO, C.CLI_NOME, C.CLI_TELEFONE');
SQL.Add('FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C');
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO');
SQL.Add('AND A.AGM_DIA = ' + QuotedStr(FormatDateTime('dd.mm.yyyy',Calendar.Date)));
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
SQL.Add('ORDER BY AGM_DIA, AGM_HORA');
Open;
First;
end;
end;
1- Rodo a aplicação e escolho um médico no ComboBox, independente de qual médico eu escolha me traz a consulta do dia. Obs. coloquei para ele começar com a data de hoje Calendar.Date:= Now;
2- Troco de Médico, continua com o mesmo resultado da consulta anterior.
3- Clico em uma data do Calendário que tem consulta gravada no banco, ele me traz o registros cadastrado, mas não troca o Médico no ComboBox.
Alguém poderia dar uma luz? se preciso for mando esta parte que estou desenvolvendo por email. Desde já obrigado pela atenção.
GOSTEI 0
Marisiana Battistella
25/11/2014
Bom, posso estar enganado, mas você não está passando o código do cliente para verificar, assim o banco está trazendo seus dados de cada médico e cada cliente, totalizando 8.
Tente colocar a condição do cliente junto no seu select.
Testei aqui e me retornou apenas os 4 registros, não sei se era isso que vc queria.
Qualquer coisa avise.
Tente colocar a condição do cliente junto no seu select.
Testei aqui e me retornou apenas os 4 registros, não sei se era isso que vc queria.
Qualquer coisa avise.
SELECT distinct A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA, M.MED_CODIGO, M.MED_NOME, C.CLI_CODIGO, C.CLI_NOME FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C WHERE A.AGM_CODIGOMED = M.MED_CODIGO AND A.AGM_CODIGOCLI = C.CLI_CODIGO;
Cada tabela que é incluida no SELECT possui uma Foreign Key que realiza o vinculo entre os dados q estão armazenados nela com os dados das demais tabelas utilizadas. Na estrutura apresentada temos 3 tabelas e as 3 contém FKs que criam esses vinculos entre os dados que elas armazenam.
Esse vinculo deve ser informado no SELECT para que o SGBD saiba localizar os dados que precisam ser retornados.
Fica muito mais fácil de estruturar uma instrução SQL corretamente quando é utilizado o padrão ANSI.
Vejam como ficaria o SELECT em questão:
SELECT A.AGM_CODIGO,
A.AGM_CODIGOMED,
A.AGM_CODIGOCLI,
AGM_DIA, AGM_HORA,
M.MED_CODIGO,
M.MED_NOME,
C.CLI_CODIGO,
C.CLI_NOME
FROM AGENDA_MEDICO A
INNER JOIN MEDICOS M
ON A.AGM_CODIGOMED = M.MED_CODIGO
INNER JOIN CLIENTES C
ON A.AGM_CODIGOCLI = C.CLI_CODIGO
GOSTEI 0
Jiraya San
25/11/2014
Boa noite Marisiana sim cada tablela que criei tem sua Chave Primária. E também estou passando o código do cliente nesta linha:
Mesmo assim vou dar uma olhada no que me passou.
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');Mesmo assim vou dar uma olhada no que me passou.
GOSTEI 0
Jiraya San
25/11/2014
Boa noite Marisiana sim cada tablela que criei tem sua Chave Primária. E também estou passando o código do cliente nesta linha:
Mesmo assim vou dar uma olhada no que me passou.
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');Mesmo assim vou dar uma olhada no que me passou.
Se puder dar uma olhada segue link:
[url]http://www.4shared.com/folder/MhHmpU1v/_online.html[/url]
GOSTEI 0
Marisiana Battistella
25/11/2014
Boa noite Marisiana sim cada tablela que criei tem sua Chave Primária. E também estou passando o código do cliente nesta linha:
Mesmo assim vou dar uma olhada no que me passou.
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');Mesmo assim vou dar uma olhada no que me passou.
Isso!
Eu apenas complementei o assunto do tópico e adaptei o SQL de acordo com o padrão ANSI.
Vale a pena aprender a utilizar, pois facilita a compreensão das instruções, melhora a performance, e ajuda a evitar que esqueçamos de incluir algum JOIN necessário.
GOSTEI 0
Renato Rubinho
25/11/2014
Jiraya,
No seu código não existe nenhum filtro pelo médico.
Em que ponto você está agora ?
Está filtrando pela data corretamente, mas você quer por médico também ? Se for só isso, ao selecionar o Médico, você tem que refazer a query filtrando pelo código do médico.
Abraççç,
Renato
No seu código não existe nenhum filtro pelo médico.
Em que ponto você está agora ?
Está filtrando pela data corretamente, mas você quer por médico também ? Se for só isso, ao selecionar o Médico, você tem que refazer a query filtrando pelo código do médico.
// Tomando como exemplo um combo que em cada linha nos primeiros 6 dígitos são o código do médico e no restante o Nome, segue exemplo para o filtro do médico:
// Obs: No onChange do Combo você coloca a chamada do Seleciona médico para atualizar ao alterar.
procedure TFrmPrincipal.SelecionaMedico;
begin
with FDQryAgendaMedico do
begin
Close;
SQL.Clear;
SQL.Add('SELECT distinct');
SQL.Add('A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA,');
SQL.Add('M.MED_CODIGO, M.MED_NOME,');
SQL.Add('C.CLI_CODIGO, C.CLI_NOME, C.CLI_TELEFONE');
SQL.Add('FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C');
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO');
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
SQL.Add('AND A.AGM_DIA = ' + QuotedStr(FormatDateTime('dd.mm.yyyy',Calendar.Date)));
if ( Trim(cbMedicos.Text) <> '' then
SQL.Add('AND M.MED_CODIGO = ' + Copy(cbMedicos.Text,1,6) ); <<<< Filtro pelo médico
SQL.Add('ORDER BY AGM_DIA, AGM_HORA');
Open;
First;
end;
end;
Abraççç,
Renato
GOSTEI 0
Jiraya San
25/11/2014
Opa boa tarde estou neste ponto, se puder dar uma olhada segue link:
http://www.4shared.com/folder/MhHmpU1v/_online.html
Coloquei os arquivos só para teste e melhor compreensão.
http://www.4shared.com/folder/MhHmpU1v/_online.html
Coloquei os arquivos só para teste e melhor compreensão.
GOSTEI 0
Renato Rubinho
25/11/2014
Buenas,
Foi o que falei no anterior.
Você seleciona o médico no dbcombo, mas não utiliza o código no filtro:
Foi o que falei no anterior.
Você seleciona o médico no dbcombo, mas não utiliza o código no filtro:
procedure TFrmPrincipal.SelecionaMedico;
begin
with FDQryAgendaMedico do
begin
Close;
SQL.Clear;
SQL.Add('SELECT distinct');
SQL.Add('A.AGM_CODIGO, A.AGM_CODIGOMED, A.AGM_CODIGOCLI, AGM_DIA, AGM_HORA,');
SQL.Add('M.MED_CODIGO, M.MED_NOME,');
SQL.Add('C.CLI_CODIGO, C.CLI_NOME, C.CLI_TELEFONE');
SQL.Add('FROM AGENDA_MEDICO A, MEDICOS M, CLIENTES C');
SQL.Add('WHERE A.AGM_CODIGOMED = M.MED_CODIGO');
SQL.Add('AND A.AGM_CODIGOCLI = C.CLI_CODIGO');
SQL.Add('AND A.AGM_DIA = ' + QuotedStr(FormatDateTime('dd.mm.yyyy',Calendar.Date)));
if ( Trim(cbMedicos.Text) <> '' then
SQL.Add('AND M.MED_CODIGO = ' + IntToStr(DSMedicos.DataSet.FieldByName('MED_CODIGO').AsInteger) ); <<<< Filtro pelo médico
SQL.Add('ORDER BY AGM_DIA, AGM_HORA');
Open;
First;
end;
end;
GOSTEI 0
Jiraya San
25/11/2014
Obrigado a todos por dispor de tempo para me ajudar, obrigado mesmo.
rrubinho, testei aqui e aparentemente está funcionando corretamente. Chegando em casa vou fazer mais uns testes e depois posto aqui a solução, por enquanto muito obrigado mesmo.
rrubinho, testei aqui e aparentemente está funcionando corretamente. Chegando em casa vou fazer mais uns testes e depois posto aqui a solução, por enquanto muito obrigado mesmo.
GOSTEI 0
Jiraya San
25/11/2014
Bom dia galera, estive afastado por um tempo devido a problemas particulares. Está funcionando da foram que preciso, muito obrigado a todos pela ajuda. Não encontrei onde finalizar o Post, se alguém puder fazer isso fico grato. Valeu mesmo!
GOSTEI 0
Marisiana Battistella
25/11/2014
Bom dia Jiraya!
Que bom que está OK !
Se não me engano, são os moderadores e os administradores que encerram os post...
Obrigada pelo feedback!
Volte sempre!
Que bom que está OK !
Se não me engano, são os moderadores e os administradores que encerram os post...
Obrigada pelo feedback!
Volte sempre!
GOSTEI 0
Jiraya San
25/11/2014
Bom dia galera, estive afastado por um tempo devido a problemas particulares. Está funcionando da foram que preciso, muito obrigado a todos pela ajuda. Não encontrei onde finalizar o Post, se alguém puder fazer isso fico grato. Valeu mesmo!
RESOLVIDO
GOSTEI 0