1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Consulta SQL

Discussão em 'Programação' iniciada por diog0silva, 3 de Junho de 2009. (Respostas: 15; Visualizações: 764)

  1. diog0silva

    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?
     
  2. Refugado

    Refugado Power Member

    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]
     
  3. diog0silva

    diog0silva Power Member

    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.
     
  4. Armadillo

    Armadillo Folding Member

    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: 4 de Junho de 2009
  5. Refugado

    Refugado Power Member

    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.
     
  6. diog0silva

    diog0silva Power Member

    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.
     
  7. Refugado

    Refugado Power Member

    Da forma que tens isso não dá para fazer JOINS.
     
  8. diog0silva

    diog0silva Power Member

    Como não dá? lol
     
  9. Poiel

    Poiel Power Member

    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
     
  10. diog0silva

    diog0silva Power Member

    Hm.. então qual será a melhor maneira de estruturá-las? Da maneira que o Amarillo sugeriu?
     
  11. gOnYs

    gOnYs Power Member

    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.
     
  12. diog0silva

    diog0silva Power Member

    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.. :\
     
  13. Armadillo

    Armadillo Folding Member

    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
     
  14. diog0silva

    diog0silva Power Member

    Hm.. obrigadão a todos pela ajuda :D
     
  15. Refugado

    Refugado Power Member

    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!
     
  16. K0mA

    K0mA Power Member

    Se calhar vou dizer asneira, mas o que tu queres é SELECT * FROM requisicoes
    De qualquer dos modos o modelo relacional está mal.
    Boa sorte-
     

Partilhar esta Página