AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 281995
Accepted
Nir
Nir
Asked: 2020-12-23 08:06:59 +0800 CST2020-12-23 08:06:59 +0800 CST 2020-12-23 08:06:59 +0800 CST

encontrar grupos com versões duplicadas

  • 772

Eu quero encontrar todos os grupos em uma tabela que tenham a versão de grupo duplicada. Um grupo pode ter várias versões de grupo. Cada versão do grupo pode ter vários membros. Uma 'versão' de grupo é definida por grpide changeDate. Um grupo considera uma duplicata se TODOS os membros ( userid, pcte hobby) em uma versão de grupo corresponderem a outra versão de grupo dentro do mesmo grupo.

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=84eb81a1a71dcee9ad3d0bd91f56120a

A groupsmesa:

Eu iria agarrar alteração de data ID do usuário pct passatempo versão do grupo *
1 1 01-01-2020 1 1 1 1
2 1 02-01-2020 1 1 2 2
3 1 03-01-2020 1 1 1 3
4 2 01-01-2020 1 0,5 1 4
5 2 01-01-2020 2 0,5 2 4
6 2 02-01-2020 1 0,5 1 5
7 2 02-01-2020 2 0,5 3 5
8 3 01-01-2020 1 0,5 1 6
9 3 01-01-2020 2 0,5 2 6
10 3 02-01-2020 1 0,4 1 7
11 3 02-01-2020 2 0,6 2 7
12 4 01-01-2020 1 0,6 1 8
13 4 01-01-2020 2 0,4 2 8
14 4 02-01-2020 1 0,6 1 9
15 4 02-01-2020 2 0,4 2 9
16 5 01-01-2020 1 0,2 2 10
17 5 01-01-2020 2 0,5 1 10
18 5 01-01-2020 3 0,3 2 10
19 6 01-01-2020 1 0,3 2 11
20 6 01-01-2020 2 0,5 1 11
21 6 01-01-2020 3 0,2 2 11
22 6 01-02-2020 1 0,2 2 12
23 6 01-02-2020 2 0,5 1 12
24 6 01-02-2020 3 0,3 2 12
25 6 01-03-2020 1 0,3 2 13
26 6 01-03-2020 2 0,3 1 13
27 6 01-03-2020 3 0,4 2 13
28 7 01-01-2020 1 0,3 2 14
29 7 01-01-2020 2 0,5 1 14
30 7 01-01-2020 3 0,2 2 14
31 7 01-02-2020 1 0,3 2 15
32 7 01-02-2020 2 0,5 1 15
33 7 01-02-2020 3 0,2 2 15
34 7 01-03-2020 1 0,3 2 16
35 7 01-03-2020 2 0,3 1 16
36 7 01-03-2020 3 0,4 2 16
37 8 01-02-2020 1 0,3 1 17
38 8 01-03-2020 1 0,3 1 18
39 8 01-03-2020 3 0,4 2 18

* Número exclusivo da versão do grupo apenas para visualização.

Resultado deve ser:

grpid
1
4
7

Explicação:

  • grpid 1 - existem 3 versões de grupo (de 1 membro) - 1 e 3 duplicadas porque userid, pct e hobby são iguais
  • grpid 2 - existem 2 versões de grupo (de 2 membros) - não duplicado porque hobby não é igual entre 5 e 7
  • grpid 3 - existem 2 versões de grupo (de 2 membros) - não duplicado porque o pct é diferente entre todos os membros
  • grpid 4 - existem 2 versões de grupo (de 2 membros) - todos os membros são duplicados porque userid, pct e userid são iguais
  • grpid 5 - existe apenas um grupo de 3 membros - não duplicado
  • grpid 6 - existem 3 versões de grupo (de 3 membros) - não duplicado - o pct mudou para cada membro do grupo entre as versões
  • grpid 7 - existem 3 versões de grupo (de 3 membros) - duplicado porque userid, pct e userid são iguais entre 28-30 e 31-33
  • grpid 8 - existem 2 versões de grupo uma com um membro e outra com 2 membros - não duplicada porque há outro membro nesse grupo

Estou usando o MySQL 5.7.

mysql select
  • 3 3 respostas
  • 119 Views

3 respostas

  • Voted
  1. Best Answer
    Vérace
    2020-12-24T03:42:34+08:002020-12-24T03:42:34+08:00

    Espero que isso forneça uma resposta:

    Isso implementa a divisão relacional "comum":

    SELECT DISTINCT grpid
    FROM groups AS g
    GROUP BY grpid, changeDate
    HAVING NOT EXISTS
        ( SELECT 1
          FROM groups AS gi
          WHERE gi.grpid = g.grpid
            AND gi.changeDate = g.changeDate
            AND NOT EXISTS
                ( SELECT 1 
                   FROM groups AS gk
                   WHERE gk.grpid = gi.grpid
                     AND gk.changeDate <> gi.changeDate
                     AND gk.userid = gi.userid
                     AND gk.pct = gi.pct
                     AND gk.hobby = gi.hobby
                )
        ) ;
    

    Resultado:

    grid
       1
       4
       7
    

    Isso implementa a divisão relacional exata , o que resulta em um código ainda mais complicado. Seu caso, onde os agrupamentos/versões são determinados por duas colunas (grpid, changeDate), faz com que pareça ainda mais complicado.

    Testado em dbffdle.uk

    Pergunta 1:

    SELECT DISTINCT g1.grpid
    FROM 
      ( SELECT grpid, changeDate
        FROM groups AS g
        GROUP BY grpid, changeDate
      ) AS g1
      JOIN
      ( SELECT grpid, changeDate
        FROM groups AS g
        GROUP BY grpid, changeDate
      ) AS g2
      ON  g1.grpid = g2.grpid
      AND g1.changeDate < g2.changeDate
    WHERE NOT EXISTS
        ( SELECT 1
          FROM groups AS gi
          WHERE gi.grpid = g1.grpid
            AND gi.changeDate = g1.changeDate
            AND NOT EXISTS
                ( SELECT 1 
                   FROM groups AS gk
                   WHERE gk.grpid = g2.grpid
                     AND gk.changeDate = g2.changeDate
                     AND gk.userid = gi.userid
                     AND gk.pct = gi.pct
                     AND gk.hobby = gi.hobby
                )
        )
       AND NOT EXISTS
        ( SELECT 1
          FROM groups AS gi
          WHERE gi.grpid = g2.grpid
            AND gi.changeDate = g2.changeDate
            AND NOT EXISTS
                ( SELECT 1 
                   FROM groups AS gk
                   WHERE gk.grpid = g1.grpid
                     AND gk.changeDate = g1.changeDate
                     AND gk.userid = gi.userid
                     AND gk.pct = gi.pct
                     AND gk.hobby = gi.hobby
                )
        )
     ;
    

    Consulta 2 que usa a GROUP_CONCATfunção do MySQL:

    SELECT DISTINCT grpid
    FROM
      ( SELECT grpid, changeDate, 
               GROUP_CONCAT( CONCAT_WS('-', userid, hobby, pct)
                             ORDER BY userid, hobby, pct
                             SEPARATOR '  '
                           ) AS groupdata 
        FROM groups AS gr
        GROUP BY grpid, changeDate
      ) AS g
    GROUP BY grpid, groupdata
    HAVING COUNT(*) > 1 ;
    
    • 3
  2. nbk
    2020-12-23T08:58:47+08:002020-12-23T08:58:47+08:00

    Você pode usar uma junção interna para isso

    Fyi mysql 8 não gosta de grupos como nome de tabela e deve ser colocado em backticks

    E as linhas id = 2 e id = 4, também são "idênticas e se enquadram em sua regra

    create table groups ( id int,  grpid int , changeDate date,  userid int,  pct double ,  hobby int );
    
    insert into groups(id , grpid , changeDate  ,userid  ,pct  ,hobby ) values
    (1  , 1      ,'2020-01-01', 1   ,    1   , 1  ),
    (2  , 1      ,'2020-01-02', 1   ,    1   , 2  ),
    (3  , 1      ,'2020-01-03', 1   ,    1   , 1  ),
    (4  , 2      ,'2020-01-01', 1   ,    0.5 , 1  ),
    (5  , 2      ,'2020-01-01', 1   ,    0.5 , 2  ),
    (6  , 2      ,'2020-01-02', 1   ,    0.5 , 1  ),
    (7  , 2      ,'2020-01-02', 1   ,    0.5 , 3  ),
    (8  , 3      ,'2020-01-01', 1   ,    0.5 , 1  ),
    (9  , 3      ,'2020-01-01', 1   ,    0.5 , 2  ),
    (10 , 3      ,'2020-01-02', 1   ,    0.4 , 1  ),
    (11 , 3      ,'2020-01-02', 1   ,    0.6 , 2  ),
    (12 , 4      ,'2020-01-01', 1   ,    0.6 , 1  ),
    (13 , 4      ,'2020-01-01', 1   ,    0.4 , 2  ),
    (14 , 4      ,'2020-01-02', 1   ,    0.6 , 1  ),
    (15 , 4      ,'2020-01-02', 1   ,    0.4 , 2  );
    
    SELECT DISTINCT g1.grpid 
    FROM `groups` g1 INNER JOIN  `groups` g2
    ON g1.grpid = g2.grpid 
    AND g1.hobby = g2.hobby 
    AND g1.pct = g2.pct 
    AND g1.userid = g2.userid
    WHERE g1.id <> g2.id
    
    | grpid |
    | ----: |
    | 1 |
    | 2 |
    | 4 |
    

    db<>fique aqui

    • 2
  3. J.D.
    2020-12-23T08:25:40+08:002020-12-23T08:25:40+08:00
    SELECT DISTINCT grpid
    FROM TableWithGroups
    GROUP BY grpid, userid, pct, hobby
    HAVING COUNT(*) > 1
    

    Isso usa as cláusulas GROUP BY e HAVING para agrupar, respectivamente, os valores nos campos que você especificou para condensar as duplicatas em uma linha e filtrar onde a contagem de linhas condensadas em cada agrupamento era maior que 1 (em outras palavras, onde havia duplicatas) .

    • 0

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve