Join a

7
Opa opa! Hoje vamos a mais um tutorial step by step onde vou falar e mostrar como fazer relacionamento entre tabelas no MySQL. O relacionamento de tabelas é necessário quando temos mais de uma tabela com informações que podem e precisam ser cruzadas, por exemplo: categorias e produtos… Cada registro na tabela produtos estará ligado a um registro da tabela categorias. Só pra vocês saberem, existem três níveis de relacionamento: nosso exemplo será um relação de 1:N (fala-se “um pra N” ou “um para muitos”) onde cada categoria (1) contém um ou mais produtos (N)… Há também o 1:1 onde cada registro de uma tabela (1) está ligado a um e somente um registro de outra tabela (1)… E há outro nível de relacionamento, mais complexo, que é o N:N onde um ou mais registros de uma tabela (N) estão relacionados a um ou mais registros de outra tabela (N), que seria o exemplo de duas tabelas “produtos” e “tags” onde um produto tem várias tags e vários produtos pertencem a uma tag. Não vou me aprofundar muito no assunto… Vou falar apenas da relação mais comum ( 1:N ) e dar exemplos de como trabalhar com elas. Para o nosso exemplo de hoje usaremos duas tabelas, chamadas “categorias” e “produtos”: 123456789101 1 CREATE TABLE `categorias` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `nome` VARCHAR( 255 ) NOT NULL ) ENGINE = MYISAM; CREATE TABLE `produtos` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `categoria_id` INT NOT NULL ,

description

asasasasas

Transcript of Join a

Page 1: Join a

Opa opa! Hoje vamos a mais um tutorial step by step onde vou falar e mostrar

como fazer relacionamento entre tabelas no MySQL.

O relacionamento de tabelas é necessário quando temos mais de uma tabela com

informações que podem e precisam ser cruzadas, por exemplo: categorias e

produtos… Cada registro na tabela produtos estará ligado a um registro da tabela

categorias.

Só pra vocês saberem, existem três níveis de relacionamento: nosso exemplo será

um relação de 1:N  (fala-se “um pra N” ou “um para muitos”) onde cada

categoria (1) contém um ou mais produtos (N)… Há também o 1:1  onde cada

registro de uma tabela (1) está ligado a um e somente um registro de outra tabela

(1)… E há outro nível de relacionamento, mais complexo, que é o N:N  onde um

ou mais registros de uma tabela (N) estão relacionados a um ou mais registros de

outra tabela (N), que seria o exemplo de duas tabelas “produtos” e “tags” onde

um produto tem várias tags e vários produtos pertencem a uma tag.

Não vou me aprofundar muito no assunto… Vou falar apenas da relação mais

comum (1:N ) e dar exemplos de como trabalhar com elas.

Para o nosso exemplo de hoje usaremos duas tabelas, chamadas “categorias” e

“produtos”:

1234567891011

CREATE TABLE `categorias` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `nome` VARCHAR( 255 ) NOT NULL) ENGINE = MYISAM; CREATE TABLE `produtos` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `categoria_id` INT NOT NULL , `nome` VARCHAR( 255 ) NOT NULL , `preco` DECIMAL( 10,2 ) NOT NULL) ENGINE = MYISAM;

E vamos inserir alguns dados para exemplo:

12345678-- Extraindo dados da tabela `categorias`INSERT INTO `categorias` VALUES(1, 'Camisetas');INSERT INTO `categorias` VALUES(2, 'Canecas'); -- Extraindo dados da tabela `produtos`INSERT INTO `produtos` VALUES(1, 1, 'Camiseta Social', 15.00);INSERT INTO `produtos` VALUES(2, 1, 'Camiseta Regata', 11.99);INSERT INTO `produtos` VALUES(3, 2, 'Caneca Grande', 12.00);

Page 2: Join a

Reparem que na tabela produtos temos uma coluna “especial”, que é a

“categoria_id” (INT)… Ela é quem ajudará a fazer a relação das duas tabelas…

Nessa coluna entrará o ID da categoria a qual o produto pertence… Ou seja: as

duas camisetas pertencem a categoria “Camisetas” (ID 1) e o terceiro produto (a

Caneca Grande) pertence a categoria “Canecas” (ID 2) e é na coluna

“categoria_id” que armazenamos esses IDs que identificam as categorias.

Esse campo responsável pela relação é normalmente chamado de foreing

key  (fk) ou “chave estrangeira”.

Mas qual a utilidade dessa tal “relação”?

Sem usar o relacionamento você poderia pegar todos os produtos e depois pegar

as informações das categorias com uma segunda consulta, assim:

123456789101112131415161718

<?php// Consulta que pega todos os produtos$sql = "SELECT * FROM `produtos` ORDER BY `nome` ASC";$query = mysql_query($sql);

while ($produto = mysql_fetch_assoc($query)) { // Aqui temos o array $produto com todos os valores do produto

// Consulta para pegar os dados da categoria: $sqlC = "SELECT * FROM `categorias` WHERE `id` = " . $produto['categoria_id']; $queryC = mysql_query($sqlC); $categoria = mysql_fetch_assoc($queryC);

echo 'Titulo: ' . $produto['nome'] . ''; echo 'Preço: ' . $produto['preco'] . ''; echo 'Categoria: ' . $categoria['nome']. ''; echo '<hr />';}

Até aí tudo bem… Não tem nenhum pecado nisso… Mas imagine que você tem

uma loja com 1000 produtos (o que não é muito), seria executada 1 consulta para

todos os produtos e, dentro do loop (while) seriam executadas outras 1000

consultas para pegar o nome da categoria a qual o produto pertence… Ou seja,

1001 consultas, o que é um absurdo.A mágica da relação

Page 3: Join a

Agora vamos montar uma consulta que DE UMA SÓ VEZ  irá pegar os dados de

cada produto e também o nome da categoria… Com isso reduziremos nossas

1001 consultas pra… uma só! Sem mistérios, sem sub-consultas, nem consultas

dentro do while() ! :D

Mas antes de mostrar o script vou ajudar a vocês entenderem como a relação é

feita… Antes a nossa consulta que pega apenas os produtos era assim:

1SELECT * FROM `produtos` ORDER BY `nome` ASC

Sua tradução seria: SELECIONAR todas as colunas da

TABELA  produtosORDENADO PELO  nome  ASCENDETEMENTE

Agora usaremos uma nova “palavra” do MySQL que é o JOIN  (tradução:

“unir”) e serve para unir resultados de duas tabelas.. ;)

Existem três tipos de JOIN mas não vou falar dos outros dois pois eles são

MUITO pouco usados… Falaremos do “INNER JOIN ” que exige que haja um

registro que corresponda a relação nas duas tabelas, ou seja: se houver um

produto sem categoria ou a categoria não existir na tabela categorias esse produto

é omitido dos resultados.

A nossa consulta ficará assim:

123

SELECT `produtos`.* FROM `produtos` INNER JOIN `categorias` ON `produtos`.`categoria_id` = `categorias`.`id` ORDER BY `produtos`.`nome` ASC

Sua tradução seria: SELECIONAR todas as colunas [da tabela produtos] da

TABELA  produtos  UNINDO A TABELA  categorias  ONDE a

colunacategoria_id  [da tabela produtos] É IGUAL a coluna  id  [da tabela

categorias] ORDENADO PELO  nome  [da tabela produtos]

ASCENDETEMENTE

Page 4: Join a

A nossa “regra de relação” acontece ali entre o ON e o ORDER BY, dizemos que

a relação entre as tabelas usará como referencia a coluna “categoria_id” da tabela

“produtos” sendo igual a coluna “id” da tabela “categorias”… Se você fosse usar

algum WHERE ele entraria depois do ON e antes do ORDER BY.

Pra quem ainda não entendeu, o ON é como o WHERE de uma consulta

normal… É a regra da relação.

Repare que agora precisamos usar um formato diferente para identificar as

colunas usando: tabela`.`coluna… Isso é necessário pois agora estamos

trabalhando com duas tabelas.

Da forma que a nossa consulta está ainda não estamos pegando o nome da

categoria… fazemos isso adicionando mais um campo na parte do SELECT,

assim:

123

SELECT `produtos`.*, `categorias`.`nome` FROM `produtos` INNER JOIN `categorias` ON `produtos`.`categoria_id` = `categorias`.`id` ORDER BY `produtos`.`nome` ASC

Agora estamos pegando também o valor da coluna "nome"  do registro

encontrado (pela relação) na tabela "categorias" .

Só que agora temos um novo problema… Nas duas tabelas existe uma coluna

chamada “nome”, e quando estivermos lá no PHP, dentro do while, não teríamos

como identificar de qual tabela pegamos as informações (veja a próxima

imagem), pois as duas seriam$produto['nome']… Precisamos então

renomear esse novo campo que adicionamos a busca, assim:Failed loading gist https://gist.github.com/d13a93554d8fe8cba2d6.json: timeout

Page 5: Join a

Agora o resultado de categorias .nome  estará presente nos resultados como

“categoria” e não “nome”… Sei que parece complicado de início mas vocês vão

entender já já.

E por fim, faremos mais uma modificação, pra evitar ficar

usandotabela .coluna  também podemos renomear as tabelas, e com isso

diminuir otamanho da consulta:Failed loading gist https://gist.github.com/2b9d02e73fbee80ad5a1.json: timeout

Nesse caso p  representará a tabela “produtos” e c  representará a “categorias”.

Sei que parece uma consulta maior e mais complicada… Mas você fará o

MySQL trabalhar muito menos se fizer assim, com JOINS, do que fazer uma 2ª

consulta dentro do while… Essa é a forma mais correta de fazer consultas

quando precisamos de informações vindas de mais de uma tabela.

Agora vamos ao nosso novo script de PHP que, sem dúvidas, é bem mais prático

e eficiente:Failed loading gist https://gist.github.com/be9c8843682edee7d9c8.json: timeoutOs outros tipos de JOINs

Existem também outros dois tipos de JOIN: o LEFT JOIN  e o RIGHT JOIN :

Se usássemos o LEFT JOIN  seriam retornados todos os produtos, independente

se eles estão ligados a uma categoria (na tabela categorias) existente ou não.

Já o RIGHT JOIN  seria exatamente o contrário: seriam retornados todos os

produtos que pertencem categorias existentes e também o nome das outras

categorias que não tem ligação com nenhum produto.

O uso desses outros tipos de JOIN é muito raro e acho que não vale a pena ficar

filosofando sobre eles enquanto se aprende sobre relacionamentos.E a relação com mais de duas tabelas?

Só pra exemplo, essa seria a consulta que pega os produtos, as categorias e o

nome do usuário que cadastrou o produto e filtrando apenas pelos produtos

ativos:Failed loading gist https://gist.github.com/f69b48cd1848812ad4f1.json: timeout

Page 6: Join a

Sim.. eu adoro consultas gigantescas. :D