Query para ranking

Olá, estou com a seguinte problemática. Fiz uma micro rede-social para os gestores, onde inicialmente o cadastro é realizado somente feito via convite, assim “medindo” a influência de cada um. Meu problema está no ranking que atualmente realiza a contagem dos convites aceitos por cada pessoa e a que tiver mais convites aceitos, obviamente fica no topo do ranking:

    SELECT 
    u.usr_id, b.ref_id, u.nome, b.c_hab, count(*) as  qnt
FROM
    tbl_user AS u
        INNER JOIN
    tbl_user b ON u.usr_id = b.ref_id
    WHERE b.c_hab = 1
GROUP BY u.nome
ORDER BY qnt DESC;

Meu problema surgiu quando solicitaram que eu contasse os convites diretos, ou seja, o gestor mandou para fulano1 (iremos chamar de nível 1), os convites que o fulano1 mandou (nível 2) e assim por diante. É confuso de explicar, mas basicamente é contar no ranking os convites dos convites, e não tenho a mínima noção de como realizar isso…

Segue a tabela de usuários para mais aprofundamento nos detalhes:

    CREATE TABLE `tbl_user` (
  `usr_id` smallint(6) NOT NULL,
  `ref_id` smallint(6) DEFAULT NULL, //Aqui é onde são armazenados as IDs de quem convidou você
  `nome` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `dt_nascimento` date DEFAULT NULL,
  `cel` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
  `endereco` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `numero` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
  `senha` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `foto` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `token` char(10) COLLATE utf8_unicode_ci DEFAULT NULL,
  `c_hab` char(1) COLLATE utf8_unicode_ci DEFAULT '0',
  `nivel` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
  `candidato` varchar(25) COLLATE utf8_unicode_ci DEFAULT NULL,
  `dt_cad` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Agradeço desde já!

Acho que se apresentar exemplos de dados nessa tabela e o resultado esperado, fica mais fácil de entender o que está tentando fazer.

Outra coisa:

ENGINE=MyISAM

Essa engine já nao é recomendada há muitos anos, dá uma procurada a respeito disso.

1 curtida

entendo tbm que convites seria uma tabela, onde meu gestor convidou x pessoas

Olá AbelBueno,

Exemplo de dados listados pela tabela:

usr_id: Campo de identificação do usuário.

ref_id: Quando por exemplo o usr_id envia um convite para a rede social, o usuário que se cadastrou a partir daquele convite vai ter como ref_id o usr_id de outro. Exemplo:
Fulano da Silva (usr_id = 1) envia o convite para Cirano de Oliveira, ao aceitar o convite, Cirano de Oliveira será usr_id = 2 e a ref_id = 1

c_hab: 0 se a conta NÃO foi ativada pelo email e 1 para indicar que foi ativado.

Com a primeira query que citei, obtenho o seguinte resultado:
ID do usuário, Referencia de onde ele veio, o nome e quantas pessoas tem a id dele como referencia, assim consigo criar um ranking para mostrar quem tem mais influência

O que espero:
O intuito do que eles solicitaram é que o usuário 1 tenha sempre o maior número de convidados, pois haverá uma contagem de pessoas que ele convidou diretamente somando com os convites realizados pelas pessoas que o usuário 1 convidou…

Exemplo:
id - ref
01 - null
02 - 01 - id 02 foi convidado por 01
03 - 02 - id 03 foi convidado por 02 que por sua vez foi convidado por 01
04 - 01
05 - 03 - id 05 foi convidado por 03, que foi convidado por 02 e que foi convidado por 01

Perceba que de certo modo todos vieram do id 01, mesmo que indiretamente… é isso que eles querem mostrar no ranking e não tenho a mínima ideia de como realizar :frowning:

Sobre a Engine:
Fui pego de surpresa com isso também. Realizei todo o desenvolvimento via MySQL Workbench e eu estou em outro computador que não tem o arquivo .SQL do projeto, resolvi exportar via phpMyAdmin, o que me gerou essas informações, inclusive a ENGINE=MyISAM.

Pois é @blayd2015, hoje percebo que falhei ao não realizar essa tabela. Durante a confecção do projeto, imaginamos que contar só as referências seria o suficiente já que estaria tudo ali na mão, porém hoje me surge essa solicitação DEPOIS que o projeto foi lançado ao público… Ainda acredito que mesmo com uma outra tabela, eu teria dificuldades para criar a query que está sendo solicitada, já que eu teria que fazer uma espécie de laço de repetição para contar os registros :frowning:

@blayd2015 em caso de dúvidas, pode ver o exemplo logo acima, creio que expliquei um pouquinho melhor do que da última vez. :slight_smile:

Alguns bancos de dados suportam Common Table Expressions, indicadas para esse tipo de problema, mas acho que o Mysql só começou a suportar isso na versao 8.

Uma maneira de fazer isso é criar uma tabela extra contendo apenas os relacionamentos, no seu caso algo como:

id   ref_id    level
1    null      null
2    1          1
3    2          1
3    1          2
4    1          1
5    3          1
5    2          2
5    1          3

Como seus dados nao mudam, isso deve ser fácil de manter e facilitar sua query. A coluna level indica a “distancia” do convidante para o convidado.

1 curtida

Legal, consegui entender bem. Vou testar isso localmente e montar a query. Irei te retornando os resultados aos poucos e te dar os upvotes devidos

Muito obrigado @AbelBueno!