SQL com Join para retornar campos correspondentes...

Delphi

14/10/2004

Olá! Tenho duas tabelas com as seguintes estruturas:

Tabela ´PRATOS´
===============

CODIGO INTEGER
DESCRICAO VARCHAR(40)

Tabela ´CARDAPIO´
=================

CODCARDAPIO INTEGER
PRATO1 INTEGER
PRATO2 INTEGER
PRATO3 INTEGER
PRATO4 INTEGER

Eu queria fazer um select na tabela cardapio com algum tipo de join que ao invés dele me retornar os campos inteiros ele me retornasse as descrições dos pratos correspondentes. Exemplo:

Ao invés de:

===============================================
CODCARDAPIO | PRATO1 | PRATO2 | PRATO3 | PRATO4
===============================================
1 | 22 | 33 | 15 | 87
===============================================

Ele me retornasse

===============================================
CODCARDAPIO | PRATO1 | PRATO2 | PRATO3 | PRATO4
===============================================
1 | CHUCHU | CAFÉ | ARROZ | AÇÚCAR
===============================================

Aproveito também para tirar uma outra dúvida. Quais indices,foreign keys eu deveria criar para essas duas tabelas, se é que deveria ter algum entre elas duas. Ah, estou usando Firebird 1.5.

Valeu pela ajuda!


Delphi32

Delphi32

Curtidas 0

Respostas

Fórum Vini

Fórum Vini

14/10/2004

Olá,
tente usar esse SQL:
Select C.CodCardapio, P1.Descricao as PRATO1, P2.Descricao as PRATO2, P3.Descricao as PRATO3, P4.Descricao as PRATO4 from Cardapio as C
  INNER JOIN Pratos as P1 ON (P1.Codigo = C.Prato1)
  INNER JOIN Pratos as P2 ON (P2.Codigo = C.Prato2)
  INNER JOIN Pratos as P3 ON (P3.Codigo = C.Prato3)
  INNER JOIN Pratos as P4 ON (P4.Codigo = C.Prato4)

(Não sei se irá funcionar para FB, mas para SQL Server parece funcionar corretamente..)


Espero ter ajudado,
Vinicius;


GOSTEI 0
Delphi32

Delphi32

14/10/2004

funcionou perfeitamente! muito obrigado mesmo!


GOSTEI 0
Vinicius2k

Vinicius2k

14/10/2004

Eu faria direferente: não usaria INNER.
Se for possível que um cardápio não tenha os 4 pratos a linha sem correspondecia total não seria considerada.
É importante também perceber a diferença entre as posições (à esquerda e à direita) das tabelas na cláusula ON do join, já que influenciam diretamente no resultado.
Por ultimo, na sintaxe do SQL Server do ´chará´, existem AS para determinar um álias para as tabelas, que não são aceitos no Firebird... vc, provavelmente, os removeu...
Bem... este seria meu código:
select
  C.CODCARDAPIO,
  P1.DESCRICAO as PRATO1,
  P2.DESCRICAO as PRATO2,
  P3.DESCRICAO as PRATO3,
  P4.DESCRICAO as PRATO4
from CARDAPIO C
left join PRATOS P1 on (C.CODCARDAPIO = P1.CODIGO)
left join PRATOS P2 on (C.CODCARDAPIO = P2.CODIGO)
left join PRATOS P3 on (C.CODCARDAPIO = P3.CODIGO)
left join PRATOS P4 on (C.CODCARDAPIO = P4.CODIGO)


E sobre a questão das FKs, elas nunca são estritamente necessárias, vc é quem decide se as quer ou não, mas se quiser, a criação das tabelas seria assim :
create table PRATOS (
  CODIGO INTEGER not null,
  DESCRICAO VARCHAR(40),
  constraint PK_PRATOS primary key (CODIGO)
);

create table CARDAPIO (
  CODCARDAPIO integer not null,
  PRATO1 integer,
  PRATO2 integer,
  PRATO3 integer,
  PRATO4 integer,
  constraint PK_CARDAPIO primary key (CODCARDAPIO),
  constraint FK_CARDAPIO_A foreign key (PRATO1) references PRATOS (CODIGO),
  constraint FK_CARDAPIO_B foreign key (PRATO2) references PRATOS (CODIGO),
  constraint FK_CARDAPIO_C foreign key (PRATO3) references PRATOS (CODIGO),
  constraint FK_CARDAPIO_D foreign key (PRATO4) references PRATOS (CODIGO)
);


T+


GOSTEI 0
Fórum Vini

Fórum Vini

14/10/2004

Eu faria direferente: não usaria INNER. Se for possível que um cardápio não tenha os 4 pratos a linha sem correspondecia total não seria considerada.

Hum.. eu nunca consegui enfiar na minha cabeça pra que servia o Left join... então é pra isso? :P
Por ultimo, na sintaxe do SQL Server do ´chará´, existem AS para determinar um álias para as tabelas, que não são aceitos no Firebird

Hum.. foi bom saber :wink:

Ae 2K, obrigado pelas correções, vc sabe que eu sou ignorante em BD :roll:

T+,
Vinicius;


GOSTEI 0
Vinicius2k

Vinicius2k

14/10/2004

Que isso chará? estamos todos no mesmo barco... aprendendo sempre...
E olhando com mais calma vi q postei um código errado tbm... perdão :oops:
O correto seria este :
select
  C.CODCARDAPIO,
  P1.DESCRICAO as DESCPRATO1,
  P2.DESCRICAO as DESCPRATO2,
  P3.DESCRICAO as DESCPRATO3,
  P4.DESCRICAO as DESCPRATO4
from CARDAPIO C
left join PRATOS P1 on (C.PRATO1 = P1.CODIGO)
left join PRATOS P2 on (C.PRATO2 = P2.CODIGO)
left join PRATOS P3 on (C.PRATO3 = P3.CODIGO)
left join PRATOS P4 on (C.PRATO4 = P4.CODIGO)

Fiz comparação dentro do ON pelo CODCARDAPIO... nada haver...

Aqui tem explicação sobre joins de ´quem entende´... :D
http://delphiforum.icft.com.br/forum/viewtopic.php?t=49308

T+


GOSTEI 0
Delphi32

Delphi32

14/10/2004

Pô galera, foi malz ae... eu fiquei tão empolgado com essa SQL que realmente tinha esquecido de mencionar que para o Firebird eu tive que remover os ´as´ como o Vinicius2k falou e agora há pouco antes de ver esses novos posts eu descobri que realmente algumas linhas não estavam sendo retornadas pela SQL, então eu também troquei os INNER JOIN por LEFT JOIN.
E quanto a minha pergunta sobre as FKs é que eu queria saber se com a existência delas essa consulta seria mais rápida. Isso porque hoje eu tenho 2.158 pratos cadastrados e 41.292 cardápios cadastrados... Vou fazer um teste para ver como fica a consulta com e sem as FKs...

Valeu ae!


GOSTEI 0
Vinicius2k

Vinicius2k

14/10/2004

O que ocorre nas FKs é que, dependendo do select, a performance aumenta porque quando vc as cria, são criados indices para suas colunas automaticamente... mas estes índices podem ser criados por vc sem necessidade de FKs, é por isso que eu mencionei que ficaria a seu critério seu uso, que basicamente, só garantem a integridade referencial no banco de dados...

T+


GOSTEI 0
POSTAR