Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

gabrieldarezzo

estrutura

Recommended Posts

Salve pessoal,

Fui responder a duvida de um colega, e me apareceu outra duvida...

Caso eu tenha um banco de dados relacional tradicional, Ex:

create database loja_imaster;

use loja_imaster;


CREATE TABLE fornecedor(
	 id	int(8) primary key auto_increment
	,nome varchar(50)
);
INSERT INTO fornecedor (nome) values ('Intel'), ('Amd');


CREATE TABLE produtos(
	 id	int(8) primary key auto_increment
	,nome varchar(50)
	,valor	decimal(5,2)
	,fornecedor_id	int (8)
);

INSERT INTO produtos (nome, valor, fornecedor_id) values 		
	 ('AMD 29030'           , 78.18, 2)
	,('Athlon'              , 500.30, 2)
	,('Phenom FX'           , 542.82, 2)
	,('Phenom X4'           , 210.50, 2)
	,('Phenom X2'           , 111.18, 2)
	
	,('Pentium 4'           , 540.18, 1)
	,('Core i7'             , 900, 1)
	,('Core i5'             , 500, 1)
	,('Core i3'             , 300, 1)
	,('Xeon série 7000'     , 1245.18, 1)
	,('Core Duo'            , 500.50, 1)
	,('Xeon'                , 200.78, 1)
	,('Pentium Dual-Core'	, 15.44, 1)
;
Basicamente aquele velho exemplo...

Produtos x Fornecedor

E eu queira criar a estrutura da foto abaixo:

f87532af3f.png

JSON-TEXT:

[{"id":"9","fornecedor_id":"1","fornecedor_nome":"Intel","produtos":[{"id":"9","nome":"Core i3","fornecedor_id":"1"},{"id":"7","nome":"Core i7","fornecedor_id":"1"},{"id":"12","nome":"Xeon","fornecedor_id":"1"},{"id":"10","nome":"Xeon s\u00e9rie 7000","fornecedor_id":"1"},{"id":"8","nome":"Core i5","fornecedor_id":"1"},{"id":"6","nome":"Pentium 4","fornecedor_id":"1"},{"id":"13","nome":"Pentium Dual-Core","fornecedor_id":"1"},{"id":"11","nome":"Core Duo","fornecedor_id":"1"}]},{"id":"5","fornecedor_id":"2","fornecedor_nome":"Amd","produtos":[{"id":"5","nome":"Phenom X2","fornecedor_id":"2"},{"id":"3","nome":"Phenom FX","fornecedor_id":"2"},{"id":"1","nome":"AMD 29030","fornecedor_id":"2"},{"id":"4","nome":"Phenom X4","fornecedor_id":"2"},{"id":"2","nome":"Athlon","fornecedor_id":"2"}]}]
Alguém sabe se tem alguma maneira facilitada?

Consegui apenas da seguinte maneira:


$conn = mysqli_connect("localhost", "root", "", "loja_imaster");
mysqli_set_charset ($conn , 'utf8');


$sql = '
	select 
		 produtos.id
		,produtos.nome
		,fornecedor.id as fornecedor_id 
		,fornecedor.nome as fornecedor_nome
	from 
		fornecedor
	inner join produtos on(
		produtos.fornecedor_id = fornecedor.id
	)
	order by fornecedor_id
';
// $stmt = mysqli_query($conn, 'set utf8');


$stmt = mysqli_query($conn, $sql);
if (!$stmt) {
	//echo "Não foi possível executar a consulta ($sql) no banco de dados: " . mysql_error();
	echo mysqli_errno($conn) . ": " . mysqli_error($conn) . "\n";			
	die();
}

//$produtos = mysqli_fetch_assoc($stmt);

$produtos = mysqli_fetch_all($stmt, MYSQLI_ASSOC);		 

$noSql = array();
$last_fornecedor = 0;


$grafo = array();

for($i = 0; $i < count($produtos); $i++){
	$produto = $produtos[$i];
	if($last_fornecedor == 0 || $last_fornecedor != $produto['fornecedor_id']){
		unset($produto['nome']);
		$produto['produtos'] = array();
		$grafo[] = $produto;		
	}
	
	$last_fornecedor = $produto['fornecedor_id'];
}
// print_r($grafo);die();

foreach($produtos as $prod){
	
	unset($prod['fornecedor_nome']);
	for($i = 0; $i < count($grafo); $i++){
		if($prod['fornecedor_id'] == $grafo[$i]['fornecedor_id']){
			// unset($prod['fornecedor_id']);
			$grafo[$i]['produtos'][] = $prod;
		}
	}
}

//Exibe estilo grafo.
// print_r($grafo);


header('Content-Type: application/json; charset=utf-8');


print json_encode($grafo);
//Saida:
//[{"id":"9","fornecedor_id":"1","fornecedor_nome":"Intel","produtos":[{"id":"9","nome":"Core i3","fornecedor_id":"1"},{"id":"7","nome":"Core i7","fornecedor_id":"1"},{"id":"12","nome":"Xeon","fornecedor_id":"1"},{"id":"10","nome":"Xeon s\u00e9rie 7000","fornecedor_id":"1"},{"id":"8","nome":"Core i5","fornecedor_id":"1"},{"id":"6","nome":"Pentium 4","fornecedor_id":"1"},{"id":"13","nome":"Pentium Dual-Core","fornecedor_id":"1"},{"id":"11","nome":"Core Duo","fornecedor_id":"1"}]},{"id":"5","fornecedor_id":"2","fornecedor_nome":"Amd","produtos":[{"id":"5","nome":"Phenom X2","fornecedor_id":"2"},{"id":"3","nome":"Phenom FX","fornecedor_id":"2"},{"id":"1","nome":"AMD 29030","fornecedor_id":"2"},{"id":"4","nome":"Phenom X4","fornecedor_id":"2"},{"id":"2","nome":"Athlon","fornecedor_id":"2"}]}]
A ideia basicamente é facilitar o Front-End explorando uma maneira estilo ?'grafo'? (array dentro de arrays)?

Exemplo:

https://fiddle.jshell.net/w5zbmxmh/

Nunca tinha pensando em estruturas assim e faz bastante sentido em alguns casos principalmente em relacionamentos estilo arvores:

\ 
 \ 
/ \ (Fornecedor)
 / \ (Computadores compatíveis)
/   \  (etc)
Enfim se alguém tiver matéria a compartilhar ou dicas de como deixar mais limpo (sem fazer 2x consultas no banco) seria bacana.

Abraço a todos

Update:

Joguei a duvida no GitHub (Forum - frontendbr) pra envolver mais gente, caso queiram acompanhar:

https://github.com/frontendbr/forum/issues/401

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não tem muito segredo e nem muita mágica.

Você tem três caminhos a seguir, o seu atual (criando o problema N + 1), realizando mais de uma consulta ou resolvendo a questão N + 1 em um SELECT IN.

Essa semana, respondi uma questão bem similar no stack overflow:

http://pt.stackoverflow.com/questions/175164/como-reunir-dados-de-duas-consultas-em-um-objeto-php/175182#175182

Veja que não estou nem um pouco preocupado com a realização de N consultas. Entretanto, o autor do tópico de lá é preguiçoso em tentar entender o simples funcionamento.

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Gabriel Heming

Pelo SELECT IN (ou apenas com SQL) não é possível criar estrutura do JSON?

Outro crise existencial questionamento será que nesse caso facilita ou atrapalha o Front-End essa estrutura?

#emBuscaDoCodigoPerfeito

Meu objetivo principal seria fazer em apenas uma estrutura de dados exibir <selects/> de acordo com <selects/> como exemplo do fiddle abaixo:

https://fiddle.jshell.net/w5zbmxmh/

Já que é muito comum no dia a dia de desenvolvimento web esse problema.

Você já trabalhou com banco de dados no-sql?

-- Off sobre o Stack

Achei que seu código estivesse pronto kkkk que era só copiar e colocar kkkk

shausHAsuaHSuaHsuhUsu

Lembrei disso:

http://i.imgur.com/SZPjHwz.jpg

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Gabriel Heming

Pelo SELECT IN (ou apenas com SQL) não é possível criar estrutura do JSON?

Não. É um problema do banco de dados relacional. Se fosse um Mongo (ou outro similar), por exemplo, seus dados estariam praticamente prontos.

Outro crise existencial questionamento será que nesse caso facilita ou atrapalha o Front-End essa estrutura?

#emBuscaDoCodigoPerfeito

Meu objetivo principal seria fazer em apenas uma estrutura de dados exibir <selects/> de acordo com <selects/> como exemplo do fiddle abaixo:

https://fiddle.jshell.net/w5zbmxmh/

Já que é muito comum no dia a dia de desenvolvimento web esse problema.

Acho que este ano estou entrando no meu nono ano como programador profissional. A verdade nua e crua é que não existe código perfeito. Tudo que você fizer, terá um porém.

Seu código é rápido em exibir o segundo select, mas pesado em questão de processamento no front-end. Por outro lado, se toda a vez que você alterar a seleção do primeiro select criar uma consulta em ajax, para retornar apenas os dados pertinentes, seu código ficará lento por causa das consultas, mas será leve, pois carregará apenas o essencial.

A pergunta principal é, o quanto cada vantagem é boa e cada desvantagem é ruim. Apesar da primeira opção usar mais memória do browser que a segunda, tende a ser pouca memória, logo é aceitável. Se chegasse a travar o browser, ai é outra história.

Você já trabalhou com banco de dados no-sql?

Já. Mas profissionalmente, as empresas que eu tenho contato são mais conservadores e preferem banco de dados relacionais. Se precisarem de mais performance, vão para alternativas corporativas pagas, como Oracle ou SQL Server.

-- Off

shausHAsuaHSuaHsuhUsu cada uma viu...

Lembrei disso:

http://i.imgur.com/SZPjHwz.jpg

Bem isso... eahaeuhaeuae

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olha, consultando a documentação do MySQL relacionada à JSON, consegui chegar nesta solução:

SELECT
        f.id, f.nome,
        CONCAT('[', group_concat(
            JSON_OBJECT('id', p.id, 'nome', p.nome, 'valor', p.valor)
        ), ']') as produtos
    FROM fornecedor as f
    INNER JOIN produtos as p ON p.fornecedor_id = f.id
    GROUP BY f.id

Tem o fiddle para teste: http://rextester.com/JXLTDN39387

Aí depois seria só dar um JSON.parse no valor de produtos (ou dependendo de como você estiver fazendo, vai ser automático, igual ao id/nome do fornecedor)...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom exemplo @AndersonMamede, vi que é da nova versão do MySQL 5.7.8 com preview para a 8.0.0.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom exemplo @AndersonMamede, vi que é da nova versão do MySQL 5.7.8 com preview para a 8.0.0.

Acho que é mais ou menos isso... pelo que entendi através deste post, o JSON foi introduzido no MySQL na versão 5.7 (o fiddle do exemplo usa o MySQL 5.7.12), e na versão 8 vai ser adicionado funções de agregação (como JSON_ARRAYAGG e JSON_OBJECTAGG).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá pessoal,

Agradeço a resposta de todos.

A ideia era justamente essa pegar um ponto de vista diferente e tentar melhorar legibilidade do código utilizando funções nativas como por exemplo o JSON_OBJECT que eu desconhecia vlw @AndersonMamede!!!

@Williams Duarte trouxe um artigo bem completo a respeito de hierarquia.

SELECT name
FROM nested_category
WHERE rgt = lft + 1;

MIND-BLOWING

@Gabriel Heming

Sobre o 'código perfeito' é talvez 'perfeito' tenha sido uma palavra palavra infeliz hehe...

Bacana a balança de 'One Flat request' x 'Multiple Slim request' é sempre legal olhar o cenário para ver qual solução se encaixa melhor, nesse caso acredito por não passar de alguns KBS então uma requisição seria ideal.

Abraço a todos e obrigado pela contribuição.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.