Inquiridor
INNER, LEFT e RIGHT

Pergunta
-
Todas as Respostas
-
Miguel,
O Inner Join realiza a união entre duas ou mais tables, e o resultado desta união representa o conjunto de dados existentes nestas tables, ou seja, os dados das tables declaradas no Inner Join são retornados.
O Left Join mostra somente o dados da table que estiver declarada do lado esquerdo do Join.
O Rigth Join mostra somente os dados da table que estiver declarada do lado direito do Join.
-
Olá, Miguel
Vamos as explicações: suponha que você tenha duas tabelas: Clientes e Vendas, relacionadas entre si. Na tabela de Clientes, você tem o cadastro de todos os clientes da loja. Na tabela de Vendas, você tem as vendas que foram realizadas pelos clientes da loja. suponha ainda que não é obrigado o cliente ser cadastrado para efetuar uma venda.
Neste cenário, podemos ter três situações:
1) Existem clientes que ainda não fizeram nenhuma compra na loja;
2) Existem vendas que foram efetuadas por clientes não cadastrados no sistema;
3) Existem vendas que foram realizadas por clientes cadastrados.Entendido o contexto acima, fica fácil de entender os JOINS. Basicamente, a sintaxe seria a abaixo:
SELECT campos FROM Clientes c TIPO_DE_JOIN JOIN Venda v ON c.cod_cliente = v.cod_cliente;
Veja agora como aplicar cada tipo de Join:
INNER JOIN: O Inner Join é utilizado nas situações em que você quer selecionar os registro das duas tabelas, desde que as mesmas possuam informações cruzadas (relacionadas). No nosso exemplo, é o JOIN que resolve a situação 3: a consulta vai retornar os clientes cadastrados que efetuaram compras.
SELECT campos FROM Clientes c INNER JOIN Venda v ON c.cod_cliente = v.cod_cliente;
OUTER JOIN: O Outer join possui o funcionamento um pouco diferente do anterior. Ao usar o Outer join, além de podermos retornar os registros das duas tabelas seguindo alguma relação, ainda podemos retornar registros que não entram nesta relação, que é a situação mais usada.
Você tem duas opções para se utilizar no Outer Join:
- LEFT OUTER JOIN (ou simplesmente LEFT JOIN): Aplica o conceito de Outer Join na tabela que se encontrar à esquerda da relação (ou seja, o resultado vem da tabela à esquerda). No nosso exemplo, é o JOIN que resolve a situação 1: a consulta retorna apenas os clientes que ainda não efetuaram nenhuma compra na loja.
SELECT campos FROM Clientes c LEFT OUTER JOIN Venda v ON c.cod_cliente = v.cod_cliente WHERE c.cod_cliente IS NULL;
- RIGHT OUTER JOIN (ou simplesmente RIGHT JOIN): Aplica o conceito de Outer Join na tabela que se encontrar à direita da relação (ou seja, o resultado vem da tabela à direita). No nosso exemplo, é o JOIN que resolve a situação 2: a consulta retorna apenas asvendas que foram realizadas por clientes não cadastrados na loja.
SELECT campos FROM Clientes c RIGHT OUTER JOIN Venda v ON c.cod_cliente = v.cod_cliente WHERE v.cod_cliente IS NULL;
Você encontra mais detalhes sobre o Join no Books Online do SQL Server. Espero que esta resposta tenha te ajudado. Qualquer duvida é só postar.
Abraço,
Herleson Pontes
Microsoft Student Ambassador/Partner
Culminis Speaker Member - Brazil
Microsoft Office Specialist – Word | Excel
Articulista da SQL Magazine
Adobe Certified – Photoshop
Líder do Grupo Office.CE (http://www.officeceara.com.br) -
Mudando um pouco de ares, irei falar de SQL (Structured Query Language) tem várias funções que vão da mais básica (INSERT, SELECT, …) até avançada (Storie de procedure), nesse post irei falar de um em que se ouve muito falar, apresento-lhe INNER JOIN. Vou considerar que você tenha alguma noção de SQL.
INNER JOIN
Em muitos casos, você poderá precisar apresentar um resultado o qual não está em apenas uma tabela, então você utiliza o INNER JOIN para fazer esse relacionamento das tabelas, fazendo da seguinte forma, como você sabe, ou deveria saber, quando duas tabelas estão interligadas, de alguma forma, precisa-se de um campo comum entre ambas (chave estrangeira).
Por exemplo:
Tenho uma escola com várias unidades e criei uma secretaria virtual. Nessa secretaria virtual, tenho os alunos cadastrados, porém eu preciso saber qual é a unidade em que esse aluno estuda. Possuímos aqui pelo menos duas tabelas, Aluno e Unidade, onde o relacionamento é um-para-muitos, porque um aluno só pode estar matriculado em uma unidade, porém uma unidade possui vários alunos. Eles se relacionam da seguinte forma, a tabela aluno tem um campo que se relaciona diretamente com o campo do código da unidade na tabela unidade, não sendo obrigatório os dois campos terem o mesmo nome, sendo apenas obrigatório os dois terem o mesmo tipo, se você não conhece SQL pode parecer complicado, mas posso assegurar-lhe que não é.
É nesse caso, em que o INNER JOIN vai ser usado, Veja:
$SQL = "SELECT Aluno.nome, Unidade.unidade";
Seleciona o campo nome da tabela aluno e campo unidade da tabela unidade$SQL .= " FROM Aluno";
A origem é a tabela Aluno. Isso significa que a tabela Aluno é o lado UM de um relacionamento, e com isso, A pesquisa é feita mais rápida;Você poderia colocar a tabela Unidade como origem.$SQL .= " INNER JOIN Unidade";
A tabela Aluno será ligada a tabela Unidade.$SQL .= " ON Aluno.cod_unidade = Unidade.cod_unidade";
Faz-se aqui o relacionamento das tabelas.$SQL .= " ORDER BY Aluno.Nome";
Coloquei que a pesquisa vai ser exibido na ordem alfabética dos nomes dos alunos.Ps.: Fiz essa pesquisa com o php, por isso está lá um .=, pois isso no php significa que estou concatenando a string SQL.
*Foi um exemplo simples, claro que nesse exemplo precisaria de mais tabelas.
Junto com o INNER JOIN, existem ainda o LEFT JOIN e o RIGHT JOIN, que funcionam de maneira semelhante. O INNER JOIN, faz o relacionamento entre duas tabelas e depois exibe o que está nas duas tabelas, já o LEFT JOIN faz a mesma coisa, porém só exibe os dados da tabela da esquerda (a primeira tabela que foi declarada) e o RIGHT JOIN, dou-lhe uma bala juquinha se você acertar…
Exatamente o que você pensou, faz o mesmo que o LEFT JOIN, porém exibe apenas os dados da tabela da direita (a segunda tabela que foi declarada).
Com isso despeço-me, até a próximaFuiii…
-
Pessoal
Estou com dificuldades numa consulta a 2 tabelas e gostaria de saber se, sendo possivel executa-la, alguem poderia me ajudar.
Tenho a primeira tabela (M) de vendas realizadas no ano anterior para determinados clientes, contendo os campos CODIGO e VALOR
A segunda tabela (P) sáo de vendas realizadas este ano para determinados clientes, tambem contendo os campos CODIGO E VALOR.
Gostaria que o resultado de minha consulta exibisse os clientes compraram este ano E que tambem compraram no ano anterior, exibindo COD, VALOR_DESTE_ANO e VALOR_ANO_ANTERIOR. (clientes que náo estáo na tabela deste ano P náo aparecem no tabela resultado (caso do cliente B)
Mas gostaria de também ter a possibilidade de somar valores caso o cliente tenha efetuado 2 compras em algum dos anos (caso cliente D e cliente E)
Exemplo:
ANO ANTERIOR
COD VALOR
A 10
B 15
C 20
D 7
E 3
E 6
ESTE ANO
COD VALOR
A 12
C 40
D 7
D 8
E 11
CONSULTA FINAL
COD VALOR_DESTE_ANO VALOR_ANO_ANTERIOR
A 12 10
C 40 20
D 16 7
E 11 9
-
Olá Eduardo,
Para resolver o seu problema, o comando SELECT seria algo parecido com o mostrado abaixo:
Code SnippetSELECT
ROW_NUMBER() OVER(ORDER BY TB1.codigo) AS [Número], TB1.valor AS Valor_Ano_Passado, TB2.valor AS Valor_Ano_Atual, (TB1.valor + TB2.valor) AS [Total]FROM
TB1 INNER JOIN TB2 ON TB1.codigo = TB2.codigoA coluna Número é apenas para gerar um índice na listagem.
Espero que este post tenha resolvido o seu problema. Se sim, lembre-se de marcá-lo como resposta da sua pergunta, ajudando outros profissionais que pesquisam pelo mesmo assunto. Qualquer duvida estamos aqui.
Abraço,
-
Herleson
Essa select prevê também o caso de haver mais de uma venda para o mesmo cliente (como o exemplo do cliente D) seja no ano corrente ou no ano anterior?
Pergunto isso pois não vi na select função SUM nem clausula GROUP BY....
Essa select que você informou é, com batatas(row_number...), a mesma select que eu estava usando e não estava funcionando (trazia valores não corretos).
Grato
-
Olá Eduardo,
Começo pedindo desculpas pela demora na resposta.
Bem, após dar uma olhada melhor no seu caso, tenho uma sugestão que resolve o caso, mas não usa JOIN. Eu pensei nessa solução por causa de um problema que poderia acontecer: você pediu que os dados de duas tabelas fossem agrupados e gerado um resultado.
Pois bem. Se eu usar o INNER JOIN, ele iria me trazer apenas os clientes que realizaram compras em ambos os anos. Se um cliente tiver realizado compras no ano anterior mas não realizou neste ano, a consulta não iria mostrar. Então, pensei em usar o FULL OUTER JOIN. Mas ai, outro problema aparecia: quando um campo mostrava o valor NULL, o SQL Server não realiza a operação de soma.
Então, decidi criar uma tabela temporária onde iria receber os valores de ambas as tabelas. Depois, bastava realizar uma SELECT simples e ele retorna o que você deseja (incluindo os clientes que compraram apenas em um dos anos considerados. Abaixo segue o código:
Script T-SQL--Criando a tabela temporária
CREATE
TABLE #Relatorio(
codigo
INT,valor_antigo
INT DEFAULT 0,valor_atual
INT DEFAULT 0,valor_total
AS (valor_antigo + valor_atual))
GO
--Inserindo os registro da Tabela 1
INSERT
INTO #Relatorio (codigo, valor_antigo) SELECT TB1.codigo, TB1.valor FROM TB1GO
--Inserindo os registro da Tabela 2
INSERT
INTO #Relatorio (codigo, valor_atual) SELECT TB2.codigo, TB2.valor FROM TB2GO
--Selecionando todos os dados
SELECT
codigo, SUM(valor_antigo) AS [Valor Antigo], SUM(valor_atual) AS [Valor Atual], SUM(valor_total) AS [Valor Total] FROM #Relatorio GROUP BY codigoGO
--Removendo a tabela temporária
DROP
TABLE #Relatorio;Eu não sei se serve para o seu cenário. Mas, de acordo com o cenário que você apresentou, resolve.
Claro que os grandes amigos do Fórum devem ter uma solução mais simples que essa. Postem! Vamos ajudar o nosso amigo Eduardo!
Espero que este post tenha resolvido o seu problema. Se sim, lembre-se de marcá-lo como resposta da sua pergunta, ajudando outros profissionais que pesquisam pelo mesmo assunto. Qualquer duvida estamos aqui.
Abraço,
-
Herleson Pontes wrote: Então, decidi criar uma tabela temporária onde iria receber os valores de ambas as tabelas. Depois, bastava realizar uma SELECT simples e ele retorna o que você deseja (incluindo os clientes que compraram apenas em um dos anos considerados. Abaixo segue o código:
Herleson
Obrigado pela resposta. Desculpe por eu ter demorado para responder! Mas quando li sua mensagem eu já havia adotado a solução de usar uma tabela temporária.
De qualquer forma muito obrigado. Estou marcando o tópico como resposta pois pode ajudar outras pessoas
Um abraço
-
Dar a consulta final que voce pede é um pouco dificil pois o valor do cliente D para a coluna VALOR_DESTE_ANO será 15 (7+8) e não 16.
A maneira que eu arranjei foi a seguinte:
select este_ano2.cod, este_ano2.valor as VALOR_DESTE_ANO, ano_anterior2.valor as VALOR_ANO_ANTERIOR
from
(select cod, SUM(valor) as valor from ESTE_ANO group by cod) as este_ano2
inner join
(select cod, SUM(valor) as valor from ANO_ANTERIOR group by cod) as ano_anterior2
on (este_ano2.cod = ano_anterior2.cod)
order by cod;
resultado:
cod | valor_deste_ano | valor_ano_anterior
-----+-----------------+--------------------
A | 12 | 10
C | 40 | 20
D | 15 | 7
E | 11 | 9
(4 rows)
Para aparecerem também aqueles clientes que apenas compraram em um dos anos:
select cod, este_ano2.valor as VALOR_DESTE_ANO, ano_anterior2.valor as VALOR_ANO_ANTERIOR
from
(select cod, SUM(valor) as valor from ESTE_ANO group by cod) as este_ano2
full outer join
(select cod, SUM(valor) as valor from ANO_ANTERIOR group by cod) as ano_anterior2
using (cod)
order by cod;
cod | valor_deste_ano | valor_ano_anterior
-----+-----------------+--------------------
A | 12 | 10
B | | 15
C | 40 | 20
D | 15 | 7
E | 11 | 9
(5 rows)
Sei que já havia ai respostas, e que já resolveste o problema, mas parece-me que não respondiam ao que era pretendido inicialmente.
Ainda sou novato nestas andanças e acredito haver uma maneira mais eficiente ou mais simples que esta. -
Rafael Fassoli wrote: Mudando um pouco de ares, irei falar de SQL (Structured Query Language) tem várias funções que vão da mais básica (INSERT, SELECT, …) até avançada (Storie de procedure), nesse post irei falar de um em que se ouve muito falar, apresento-lhe INNER JOIN. Vou considerar que você tenha alguma noção de SQL.
INNER JOIN
Em muitos casos, você poderá precisar apresentar um resultado o qual não está em apenas uma tabela, então você utiliza o INNER JOIN para fazer esse relacionamento das tabelas, fazendo da seguinte forma, como você sabe, ou deveria saber, quando duas tabelas estão interligadas, de alguma forma, precisa-se de um campo comum entre ambas (chave estrangeira).
Por exemplo:
Tenho uma escola com várias unidades e criei uma secretaria virtual. Nessa secretaria virtual, tenho os alunos cadastrados, porém eu preciso saber qual é a unidade em que esse aluno estuda. Possuímos aqui pelo menos duas tabelas, Aluno e Unidade, onde o relacionamento é um-para-muitos, porque um aluno só pode estar matriculado em uma unidade, porém uma unidade possui vários alunos. Eles se relacionam da seguinte forma, a tabela aluno tem um campo que se relaciona diretamente com o campo do código da unidade na tabela unidade, não sendo obrigatório os dois campos terem o mesmo nome, sendo apenas obrigatório os dois terem o mesmo tipo, se você não conhece SQL pode parecer complicado, mas posso assegurar-lhe que não é.
É nesse caso, em que o INNER JOIN vai ser usado, Veja:
$SQL = "SELECT Aluno.nome, Unidade.unidade";
Seleciona o campo nome da tabela aluno e campo unidade da tabela unidade$SQL .= " FROM Aluno";
A origem é a tabela Aluno. Isso significa que a tabela Aluno é o lado UM de um relacionamento, e com isso, A pesquisa é feita mais rápida;Você poderia colocar a tabela Unidade como origem.$SQL .= " INNER JOIN Unidade";
A tabela Aluno será ligada a tabela Unidade.$SQL .= " ON Aluno.cod_unidade = Unidade.cod_unidade";
Faz-se aqui o relacionamento das tabelas.$SQL .= " ORDER BY Aluno.Nome";
Coloquei que a pesquisa vai ser exibido na ordem alfabética dos nomes dos alunos.Ps.: Fiz essa pesquisa com o php, por isso está lá um .=, pois isso no php significa que estou concatenando a string SQL.
*Foi um exemplo simples, claro que nesse exemplo precisaria de mais tabelas.
Junto com o INNER JOIN, existem ainda o LEFT JOIN e o RIGHT JOIN, que funcionam de maneira semelhante. O INNER JOIN, faz o relacionamento entre duas tabelas e depois exibe o que está nas duas tabelas, já o LEFT JOIN faz a mesma coisa, porém só exibe os dados da tabela da esquerda (a primeira tabela que foi declarada) e o RIGHT JOIN, dou-lhe uma bala juquinha se você acertar…
Exatamente o que você pensou, faz o mesmo que o LEFT JOIN, porém exibe apenas os dados da tabela da direita (a segunda tabela que foi declarada).
Com isso despeço-me, até a próximaFuiii…
Rafael, ótima explicação, pelo que entendi Inner Join funciona como where para "ligar" duas tabelas. É isso mesmo?
-
Caros amigos
Estou procurando há meses sobre como montar o SELECT para fazer a busca em 4 tabelas distintas, mas sem sucesso. Bom, vamos por partes para vocês entenderem o sistema:
1) Tabelas: as tabelas as quais preciso realizar a busca são (elas já encontram-se prontas e criadas):
- cadastro: tabela de cadastro de pacientes (nome, endereço, telefone, cep etc)
- cadastro_interesses: tabela dos CURSOS que o paciente (tabela "cadastro") possui interesse (ele escolhe no momento do cadastro através de um check box)
- cadastro_realizeis: tabela dos CURSOS que o paciente (tabela "cadastro") realizou na clínica (ele escolhe no momento do cadastro através de um check box)
- cadastro_tratamentos: tabela dos TRATAMENTOS que o paciente (tabela "cadastro") possui interesse (ele escolhe no momento do cadastro através de um check box)
2) O sistema: é um sistema de busca para uma clínica, onde o médico poderá fazer a busca nos vários campos das tabelas supra descritas, conforme mostra a tela a seguir:
3) A consulta, pelo médico, poderá ser feita de forma aleatória, ou seja, qualquer um dos campos da busca acima.
4) Minha sintaxe atual : não está mostrando todos os cadastrados. A busca está incompleta pois aparecem somente os cadastrados que possuem registro na tabela cadastro_interesses. Se fizer a busca filtrando, também, com os outros campos, não aparece! Eis a sintaxe:
$result=mysql_query(" SELECT cadastro.*, cadastro_interesses.*, cadastro_realizeis.*, cadastro_tratamentos.* FROM cadastro LEFT JOIN cadastro_interesses ON cadastro.codigo = cadastro_interesses.codigo_cadastro LEFT JOIN cadastro_realizeis ON cadastro_interesses.codigo_cadastro = cadastro_realizeis.codigo_cadastro LEFT JOIN cadastro_tratamentos ON cadastro_realizeis.codigo_cadastro = cadastro_tratamentos.codigo_cadastro WHERE cadastro.nome LIKE '%$letra%' AND cadastro.sexo LIKE '$sexo%' AND cadastro.nacionalidade LIKE '$nacionalidade2%' AND cadastro.naturalidade LIKE '$naturalidade2%' AND cadastro.bairro LIKE '$bairro2%' AND cadastro.cidade LIKE '$cidade2%' AND cadastro.estado LIKE '$estado2%' AND cadastro.escolaridade LIKE '$escolaridade%' AND cadastro.profissao LIKE '$profissao2%' OR cadastro_interesses.codigo_interesse LIKE '%$interesses2%' OR cadastro_realizeis.codigo_realizei LIKE '%$realizeis2%' OR cadastro_tratamentos.codigo_tratamento LIKE '%$tratamentos2%' GROUP BY cadastro.codigo ORDER by cadastro.nome ASC LIMIT $ini,$mostra "); $result2=mysql_query(" SELECT cadastro.*, cadastro_interesses.*, cadastro_realizeis.*, cadastro_tratamentos.* FROM cadastro INNER JOIN cadastro_interesses ON cadastro.codigo = cadastro_interesses.codigo_cadastro INNER JOIN cadastro_realizeis ON cadastro_interesses.codigo_cadastro = cadastro_realizeis.codigo_cadastro INNER JOIN cadastro_tratamentos ON cadastro_realizeis.codigo_cadastro = cadastro_tratamentos.codigo_cadastro WHERE cadastro.nome LIKE '$letra%' AND cadastro.sexo LIKE '$sexo%' AND cadastro.nacionalidade LIKE '$nacionalidade2%' AND cadastro.naturalidade LIKE '$naturalidade2%' AND cadastro.bairro LIKE '$bairro2%' AND cadastro.cidade LIKE '$cidade2%' AND cadastro.estado LIKE '$estado2%' AND cadastro.escolaridade LIKE '$escolaridade%' AND cadastro.profissao LIKE '$profissao2%' AND cadastro_interesses.codigo_interesse LIKE '$interesses2%' AND cadastro_realizeis.codigo_realizei LIKE '$realizeis2%' AND cadastro_tratamentos.codigo_tratamento LIKE '$tratamentos2%' "); $total=mysql_num_rows($result2); $reg=0; while ($myrow=mysql_fetch_array($result)) {