GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Ter tabela com nomes mais usados nos registros das outras tabelas?

banco
Tags: #<Tag:0x00007f9d2473df48>

#21

Mais ou menos. Eu tenho bastante experiência com SQL, porém isso que estou tentando fazer é bem avançado pra mim, e mesmo com os seus exemplos, e mesmo a sintaxe do SQL ser bem clara, estou sim com algumas dificuldades para entender. Mas vamos por partes então.

Vamos ver o que eu entendi nessa parte. Tu está pegando o campo conteúdo pela ordem de repetição deles? O que eu ainda não entendi é que o campo é um texto, e eu quero que essa ordem seja dada pelas palavras dos mesmos.

Eu realmente não entendi essa parte.[quote=“LostSoldier, post:20, topic:343654”]
COUNT(*)
[/quote]

É uma função que retorna a quantidades de registros do select certo?

Já vi muito sobre o GROUP BY, mas nesse caso, eu não estou entendendo.[quote=“LostSoldier, post:20, topic:343654”]
ORDER BY COUNT(*) DESC?
[/quote]

Tu está ordenando os registros pelo os que se repetem certo?


#22

Essa sua bastante experiência com SQL precisa ser bem treinada :joy:

Brincadeiras a parte, vamos la…

Quando se usa agrupamento GROUP BY, você quer deixar em uma unica linha, várias encontradas, um exemplo, na tabela itens você tem conteudos com os nomes Rock 2 vezes e MPB 3 vezes

Pois bem, se você usar um select comum… Você terá varias linhas “repetidas” correto?

SELECT conteudo FROM itens;

Rock
MPB
Rock
MPB
MPB

Com o agrupamento fica assim:

SELECT conteudo FROM itens GROUP BY conteudo;

Rock
MPB

Quando se usa COUNT(*) em agrupamentos, alem de juntar os repetidos, ele conta quantas repetições encontrou para aquele agrupamento…

SELECT conteudo, COUNT(*) repeticoes FROM itens GROUP BY conteudo;

Rock, 2
MPB, 3

Como havia lhe falado lá em cima, não me recordo se o mysql permite funções como COUNT em declarações como ORDER BY, mas de todo modo se eu quiser ordenar a consulta pela quantidade de repetições do maior para o menor ficaria…

SELECT conteudo, COUNT(*) repeticoes FROM itens GROUP BY conteudo 
ORDER BY COUNT(*) DESC;

MPB, 3
Rock, 2

Clareou mais agora as idéias?

Agora encaixando essa lógica no seu problema, você tem a tabela gostos e digamos que além dos conteudos, queira gravar também quantas vezes aquele gosto foi citado, é ai que você precisa criar uma coluna int para guardar o COUNT que eu tinha nomeado como qtd e você mudou para conteudo, complicadndo mais ainda o entendimento :joy: pegou?

E pra finalizar, a quantidade de colunas que você usar no select, será o “values” para o insert into gostos, ou seja, se selecionei uma coluna, devo usar apenas uma no insert, etc…


#23

Agora sim eu entendi toda a estrutura, e estou testando todos os comandos do evento, porém como eu disse, eu preciso saber as PALAVRAS, e com o SELECT, eu estou recebendo as frases. Usando o mesmo exemplo seu…Se ao Rock e MPB estiverem dentro de frases, e tu quiser fazer esse mesmo procedimento?


#24

Essa solução irá agrupar e mandar os valores que estiverem no campo conteudo e forem iguais, se você guarda frases ao invés de termos aí complica bem… para o que você precisa será algo bem mais complexo e eu não faço idéia, talvez você consiga algum norte pesquisando sobre BI

E discordo, em nenhum momento você citou que guardava frases no campo conteudo…


#25

Se tu não sabe, imagina eu :joy:. Bem, eu tenho uma ideia, mas não sei aplicar no Mysql, talvez tu saiba. Seria possível fazer um split utilizando o caractere " " e salvar cada palavra em uma tabela temporária? Assim basta eu realizar esse procedimento nessa tabela certo?


#26

Sobre split, algo nesse post

Agora tente adaptar à sua necessidade… boa sorte ai

Já vai pesquisando sobre subqueries também, talvez possa precisar, ou usar a tabela temporária pode ser uma saída…


#27

Eu consegui dessa maneira:

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');
       
SELECT SPLIT_STR((SELECT group_concat(conteudo SEPARATOR ' ') from itens), ' ', 1);

Porém a cada SELECT ele retorna um resultado do SPLIT. Para retornar tudo e criar a tabela temporária, eu precisaria ficar incrementando esse index aí. Sabe como eu posso fazer isso? Desde já peço desculpas pela ignorância, mas estou mesmo com dificuldade de me adaptar a essa sintaxe. E eu tenho medo de mexer com loops e provocar algum problema de performance.


#28

Exemplo na net é o que não falta…

Aproveita pra ir treinando SQL, logo você fica craque e te garanto, é só assim que se aprende.

Quanto a usar loops em base de dados, como falei antes, evite ao máximo, diferente das linguagens, a base sofre com performance principalmente se usar cursores…


#29

Eu já vi esse exemplo várias vezes, mas não consegui fazer nesse meu código.

Eu não queria usar, mas não vejo outra alternativa. Aliás, eu tentei e não deu certo. Vou pesquisar mais sobre cursores e tentar implementar então.


#30

Pronto. Consegui fazer o split e adaptei tudo a minha necessidade. Existe um pequeno bug no split, mas isso eu resolvo depois. Vamos por partes.

A função que eu utilizo para fazer o split:

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');

Eu criei um Stored Procedure para fazer o split e salvar na tabela temporária:

DELIMITER$$
CREATE PROCEDURE split_all(uid mediumint) begin
BEGIN
SET @grouped = (SELECT group_concat(conteudo SEPARATOR ' ') from itens WHERE usuario=uid);       
SET @countTotal = (select (LENGTH(@grouped) - LENGTH(replace(@grouped,' ',''))) / LENGTH(' '));
SET @i = 2;

CREATE TEMPORARY TABLE gostos_tmp SELECT SPLIT_STR(@grouped, ' ', 1);

WHILE @i <= @countTotal DO
	INSERT INTO gostos_tmp SELECT SPLIT_STR(@grouped, ' ', @i);
	SET @i = @increment+1;
END WHILE;
END$$
DELIMITER ;

E o corpo do evento ficou assim:

BEGIN
DECLARE uid MEDIUMINT DEFAULT 0;
DECLARE meu_cursor CURSOR FOR SELECT DISTINCT usuario FROM itens;
OPEN meu_cursor;
loop1: LOOP
	FETCH meu_cursor into uid;
	CALL split_all(uid);
	INSERT INTO gostos(gosto) SELECT conteudo FROM itens 
	ORDER BY COUNT(*) DESC;
	INSERT INTO usuario_gosta(muid, usuario, gosto) 
	SELECT m.id, i.usuario, i.conteudo FROM gostos AS m
	INNER JOIN itens AS i ON i.conteudo = m.gosto;
END LOOP loop1;
END

Eu criei um Stored Procedure com o mesmo conteúdo do evento, para testar. E quando eu o chamo, recebo esta mensagem:


#31

Alguém?