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

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?

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…

1 curtida

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?

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…

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?

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…

1 curtida

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.

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…

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.

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:

Alguém?