Consulta SQL

diog0silva

Power Member
Boas. Tou com uma dúvida numa consulta.

Imaginem que um clube video tem clientes, funcionários e dvd's.

Tenho quatro tabelas: clientes, funcionarios, requisições e dvd's.

A tabela requisições tem duas chaves estrangeiras: uma da tabela clientes e outra da tabela funcionarios, porque ambos podem fazer requisições. (E tem a chave estrangeira da tabela dvd's, mas para o caso não interessa.)

Eu queria fazer uma consulta que listasse todas as requisições efectuadas e o nome da pessoa que a requisitou (seja cliente, seja funcionário).

SELECT req_data, req_dvd_cod, (req_clt_num ou req_func_num) FROM tab_requisicoes

Ou seja, queria que, se a requisição fosse dum cliente seleccionava o req_clt_num e se a requisição fosse dum funcionário seleccionava o req_func_num. É possivel?
 
Olá,

Para isso tens de usar a junção de tabelas na consulta!
Penso que para o teu caso terá de ser o:

  • FULL JOIN: Return rows when there is a match in one of the tables;
Sintaxe:

Código:
SELECT lista_colunas
FROM tabela1 FULL JOIN tabela2
        ON condição_de_junção1
    FULL JOIN tabela3
        ON condição_de_junção2
[ORDER BY lista_de_ordenação]
 
Refugado, acho que não resolve o meu problema.

Para existir uma requisição, esta tem que estar associada a um e um só registo ou na tabela funcionários ou na tabela clientes. Portanto, usar FULL JOIN ou INNER JOIN, para o que quero, é igual.

Eu queria era, se a requisição pertencer a um cliente, então selecciona o campo req_clt_num.
Se pertencer a um funcionário, então selecciona o campo req_func_num.
 
Quer-me parecer que tens as tabelas mal normalizadas. Na minha opinião, terias que ter as seguintes tabelas:

Tabela Clientes
*ID_CLIENTE
NOME_CLIENTE
ID_TIPO_CLIENTE


Tabela Tipo_Cliente (nesta tabela tens os tipos de clientes existentes: clientes normais, funcionários, empresas, etc...)
*ID_TIPO_CLIENTE
DESCRICAO


Tabela Funcionários
*ID_FUNCIONARIO


Tabela Funcionarios-Clientes (Esta tabela liga com a Tabela_Funcionarios e a Tabela_Clientes)
*ID_FUNCIONARIO
*ID_CLIENTE

Tabela DVDs
*ID_DVD
NOME_DVD


Tabela Requisições
*ID_REQUISICAO
ID_CLIENTE
DATA_INI
DATA_FIM
DATA_ENTREGUE

Neste caso, a query será tao simples quanto:
Código:
SELECT Tabela_Requisições.*, Tabela_Clientes.NOME_CLIENTE 
FROM Tabela_Requisições 
Inner Join Tabela_Clientes On (Tabela_Requisições.ID_CLIENTE = Tabela_Clientes.ID_CLIENTE)
cumps
 
Última edição:
Para existir uma requisição, esta tem que estar associada a um e um só registo ou na tabela funcionários ou na tabela clientes. Portanto, usar FULL JOIN ou INNER JOIN, para o que quero, é igual.

Não serão dois? Tem de haver o registo na tabela requisição e registo correspondente na tabela cliente/funcionário!

O JOIN faz isso mesmo, junção de tabelas onde se verifica a correspondência de FK com PK.
 
Eu neste momento tenho as tabelas assim:

tab_cliente
clt_bi PK
clt_nome

tab_funcionario
func_bi PK
func_nome

tab_dvd
dvd_cod PK
dvd_descricao

tab_requisicao
req_num PK
req_clt_bi FK
req_func_bi FK
req_dvd_cod FK

Ou seja, quando a requisição é feita por um cliente, põe-se o BI do cliente no campo req_clt_bi, e o campo req_func_bi fica a NULL.

Quando a requisição é feita por um funcionário, é ao contrário: BI do funcionário no campo req_func_bi e o campo req_clt_bi fica a NULL.

Tipo, eu podia fazer o que o Armadillo sugeriu. Mas este exemplo que dei (o clube de video) é inventado. Estou a trabalhar com uma BD muito mais complexa e estou a geri-lá através de uma aplicação em VB.NET. E estar a alterar o modelo relacional agora, teria que alterar o código quase todo :\

Se alguém souber uma outra maneira de fazer aquela consulta, agradeço.
 
Claro que dá.....:p

Uma maneira de fazer, é:

select req_num, req_dvd_cod, dvd_descricao, clt_nome as nome
from tab_requisicao inner join tab_cliente ON req_clt_bi = clt_bi
inner join tab_dvd on req_dvd_cod = dvd_cod
union
select req_num, req_dvd_cod, dvd_descricao, func_nome as nome
from tab_requisicao inner join tab_funcionario ON req_clt_bi = func_bi
inner join tab_dvd on req_dvd_cod = dvd_cod

Existem outras, utilizando so um select com left join..

Mas, para mim, tens a mal estruturado as tabelas
 
Na tabela de requisições só fazia uma alteração

tab_requisicao
req_num PK
req_clt_bi FK
req_func_bi FK
req_dvd_cod FK


para quê que tens este dois campos ?

req_clt_bi FK
req_func_bi FK

quando podes ter apenas um campo de cliente que te diz qual foi o autor da requisição se depois quiseres saber
se o autor da requisição é Cliente ou Funcionário alteras a tabela de Clientes e colocas um campo Tipo_Cliente com Fk para uma tabela de tipos de cliente penso que assim fará mais sentido.

Ou seja ficava assim:

tab_cliente
clt_bi PK
clt_nome
clt_Tipo FK

Tab_TipoCliente
clt_ID PK
Designacao


tab_dvd
dvd_cod PK
dvd_descricao

tab_requisicao
req_num PK
Cod_Cliente FK
req_dvd_cod FK

Cumps.
 
Portanto, não é recomendável ter uma tabela que receba mais que uma chave estrangeira quando não podem estar ambas preenchidas em simultaneo, é isso? Basicamente, se existir uma chave estrangeira é para estar preenchida.

Mas já agora, ter da maneira que tenho é uma falha grave? É que vou ter que alterar o meu programa quase todo.. e não vai para pequeno.. :\
 
depende do que aches grave. Aqui no teu caso, estás a ter alguns problemas por teres uma falha na análise.
Mas é assim, nao se deve "sobre-normalizar" já que ás vezes complica mais do que resolve. Muito software profissional que anda aí à venda, muitas das tabelas não estão normalizadas da melhor forma (aparente), mas a verdade é que a coisa funciona.

Eu aconselharia a mudar a estrutura agora e perder um(??) dia a readaptar o código à nova estrutura, do que daqui a uns tempos ter que mexer no código e perder mais tempo a fazer uma coisa que deveria ser simples, mas que se torna moroso devido à estrutura de dados. Tem em conta também o tempo que tens disponível, e se este for pouco, mais vale deixar estar como está do que alterar.
Essa decisão cabe-te a ti tomar, já que tens perfeita noção do que já está feito e o que falta ainda fazer ;)

cumps
 
Vi a estrutura das tabelas assim na diagonal e sai-me com aquela.. My bad. :P
É que pessoalmente utilizo uma forma diferente de estruturar os problemas!
 
Se calhar vou dizer asneira, mas o que tu queres é SELECT * FROM requisicoes
De qualquer dos modos o modelo relacional está mal.
Boa sorte-
 
Back
Topo