none
Select com relação entre tabelas RRS feed

  • Pergunta

  • Bom dia a todos.

     

    Olhei por diversos tópicos sobre relação entre tabelas, mas o conceito de JOIN ainda é um tanto abstrato pra mim. Acredito que se resolver essa situação poderei resolver as semelhantes no futuro. Segue o meu problema.

     

    Estou desenvolvendo um portal institucional onde REVENDAS anunciarão PRODUTOS de determinadas CATEGORIAS. Dada essa relação, criei uma quarta tabela chamada PRODUTOREVENDA onde guardo as FKeys ProdutoID e RevendaID de suas respectivas tabelas. Na página administrativa das revendas cadastradas, preciso montar um select que retorne essas duas informações, porém através de seus nomes ('Produto' e 'Categoria') e não os ID's. Abaixo segue um dos inúmeros selects que montei, para que visualizem o cenário. Esse select retorna dados duplicados por não estar estruturado corretamente.

     

    SELECT p.Produto, c.Categoria
    FROM Produtos AS p INNER JOIN ProdutoRevenda AS pr ON p.ProdutoID = pr.ProdutoID RIGHT OUTER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID

    WHERE (pr.RevendaID = @RevendaID)

    ORDER BY c.Categoria

     

    Agradeço a todos que puderem me dar algum auxílio.

     

    Um abraço,

    João Cunha

    sábado, 23 de fevereiro de 2008 13:28

Respostas

  • Olá João,

     

    É perfeitamente compreensível o quanto esse conceito pode ser abstrato. Normalmente, quando estou ensinando SQL, o tópico de JOINs é que costuma causar dificuldades. Com o tempo e a prática você verá que eles não tem nada de díficil e que essa adversidade é bem mais pelo fato dele ser para você uma novidade.

     

    Code Snippet

    SELECT p.Produto, c.Categoria
    FROM
     Produtos AS p
     INNER JOIN ProdutoRevenda AS pr ON p.ProdutoID = pr.ProdutoID
     INNER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID

    WHERE (pr.RevendaID = @RevendaID)

    ORDER BY c.Categoria

     

     

    O SELECT acima vai retornar dados duplicados, mas não por estar incorretamente estruturado. Note que você está fazendo uma junção entre ProdutoRevenda. Isso significa que se na tabela ProdutoRevenda, o produto aparecer mais de uma vez, o seu SELECT deve contempla-lo mais de uma vez. Existem duas saídas práticas para isso. A primeira é usar o DISTINCT. Ex:

     

    Code Snippet

    SELECT DISTINCT p.Produto, c.Categoria
    FROM
     Produtos AS p
     INNER JOIN ProdutoRevenda AS pr ON p.ProdutoID = pr.ProdutoID
     INNER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID

    WHERE (pr.RevendaID = @RevendaID)

    ORDER BY c.Categoria

     

     

    Ou se você preferir, pode optar pelo IN (Pode lhe parecer mais complicado)

     

    Code Snippet
    SELECT p.Produto, c.Categoria
    FROM
     Produtos AS p
     INNER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID
    WHERE
     p.ProdutoID IN
     (SELECT pr.ProdutoID FROM ProdutoRevenda WHERE (pr.RevendaID = @RevendaID))
    ORDER BY c.Categoria

     

     

    Acho que ainda é muito cedo para entrar em detalhes de outras construções possíveis ou porque uma seria melhor que outra. Por enquanto (apenas enquanto você está se familiarizando), escolha a que julgar mais conveninte.

     

    [ ]s,

     

    Gustavo

    sábado, 23 de fevereiro de 2008 14:10

Todas as Respostas

  • Olá João,

     

    É perfeitamente compreensível o quanto esse conceito pode ser abstrato. Normalmente, quando estou ensinando SQL, o tópico de JOINs é que costuma causar dificuldades. Com o tempo e a prática você verá que eles não tem nada de díficil e que essa adversidade é bem mais pelo fato dele ser para você uma novidade.

     

    Code Snippet

    SELECT p.Produto, c.Categoria
    FROM
     Produtos AS p
     INNER JOIN ProdutoRevenda AS pr ON p.ProdutoID = pr.ProdutoID
     INNER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID

    WHERE (pr.RevendaID = @RevendaID)

    ORDER BY c.Categoria

     

     

    O SELECT acima vai retornar dados duplicados, mas não por estar incorretamente estruturado. Note que você está fazendo uma junção entre ProdutoRevenda. Isso significa que se na tabela ProdutoRevenda, o produto aparecer mais de uma vez, o seu SELECT deve contempla-lo mais de uma vez. Existem duas saídas práticas para isso. A primeira é usar o DISTINCT. Ex:

     

    Code Snippet

    SELECT DISTINCT p.Produto, c.Categoria
    FROM
     Produtos AS p
     INNER JOIN ProdutoRevenda AS pr ON p.ProdutoID = pr.ProdutoID
     INNER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID

    WHERE (pr.RevendaID = @RevendaID)

    ORDER BY c.Categoria

     

     

    Ou se você preferir, pode optar pelo IN (Pode lhe parecer mais complicado)

     

    Code Snippet
    SELECT p.Produto, c.Categoria
    FROM
     Produtos AS p
     INNER JOIN Categorias AS c ON c.CategoriaID = p.CategoriaID
    WHERE
     p.ProdutoID IN
     (SELECT pr.ProdutoID FROM ProdutoRevenda WHERE (pr.RevendaID = @RevendaID))
    ORDER BY c.Categoria

     

     

    Acho que ainda é muito cedo para entrar em detalhes de outras construções possíveis ou porque uma seria melhor que outra. Por enquanto (apenas enquanto você está se familiarizando), escolha a que julgar mais conveninte.

     

    [ ]s,

     

    Gustavo

    sábado, 23 de fevereiro de 2008 14:10
  • Perfeito, Gustavo! Era exatamente isso que estava precisando. Estou estudando mais sobre o funcionamento dos JOINS para poder fazer essas operações.

     

    Muito obrigado pela paciência!

    sábado, 23 de fevereiro de 2008 14:45
  • Surgiu um novo problema: estou desenvolvendo esse sistema em ASP.NET C# através de DataSets Tipados. Quando fui montar minha query para DELETE, ela funciona legal no test query, mas não funciona em tempo de execução. Aliás, isso é algo que eu enfrento muito...

     

    Segue a query:

     

    DELETE FROM ProdutoRevenda
    WHERE     (ProdutoID = @Original_ProdutoID) AND (RevendaID = @Original_RevendaID)

     

    P.S.: É a query que vou usar quando desejar excluir um PRODUTO de uma determinada REVENDA.

    sábado, 23 de fevereiro de 2008 16:21
  • Olá João,

     

    Inicialmente acho que você deveria separar os posts (o assunto inicial era sobre JOINs e foi resolvido). Isso permite que outros participantes foquem diretamente na dúvida identificando-a através de seu tópico.

     

    No caso do DELETE, ele está correto. Pode ser que em tempo de execução, os atributos @Original_ProdutoID e Original_RevendaID) não estejam sendo corretamente atribuídos. Tente fazer uma query de SELECT com esses valores e verifique se algum registro é retornado.

     

    [ ]s,

     

    Gustavo

    segunda-feira, 25 de fevereiro de 2008 01:35
  • Obrigado, Gustavo!

     

    Um abraço.

    segunda-feira, 25 de fevereiro de 2008 11:45