Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Filtre linhas com vários vetores grandes


Isso usa o conceito de uma cross join aka Produto cartesiano (todas as permutações). Portanto, seus arrays produzem uma tabela derivada (na memória) com uma contagem de linhas de x*y*z , onde esses x,y,z são os tamanhos das matrizes. Se você forneceu matrizes de tamanho 3,4 e 5, a tabela derivada teria uma contagem de linhas de 3*4*5=60.

Sua correspondência de matriz fornecida que produz uma linha era apenas 4*1*1=4

thing7 abaixo está a tabela principal que você está procurando. O covering index deve fazer essa coisa voar mesmo com uma tonelada de dados nela. Um índice de cobertura é aquele em que as informações fornecidas são fornecidas por meio da varredura de b-tree do índice e que uma leitura de página de dados não é necessária. Por quê? Porque os dados necessários estão no índice. E no seu caso, extremamente fino.

As tabelas A B C são para uso como seus arrays.

A única outra coisa a dizer é que toda tabela derivada requer um nome. Então demos o nome xDerived na consulta. Pense em uma tabela derivada como algo retornado e usado na memória. Não é uma mesa física.

Esquema

create table thing7
(   id int auto_increment primary key,
    A int not null,
    B int not null,
    C int not null,
    index(A,B,C) -- covering index (uber-thin, uber-fast)
);

insert thing7(A,B,C) values
(1,2,7),  
(1,2,8), 
(2,2,1), 
(1,3,1);

create table A
(   id int auto_increment primary key,
    value int
);
create table B
(   id int auto_increment primary key,
    value int
);
create table C
(   id int auto_increment primary key,
    value int
);

Teste 1

truncate table A;
truncate table B;
truncate table C;
insert A (value) values (1),(2),(3),(4);
insert B (value) values (2);
insert C (value) values (7);

select t7.* 
from thing7 t7  
join 
(   select A.value as Avalue, B.value as Bvalue, C.value as Cvalue 
    from A 
    cross join B 
    cross join C 
    order by a.value,b.value,c.value 
) xDerived 
on xDerived.Avalue=t7.A and xDerived.Bvalue=t7.B and xDerived.Cvalue=t7.C; 
+----+---+---+---+
| id | A | B | C |
+----+---+---+---+
|  1 | 1 | 2 | 7 |
+----+---+---+---+

..

Teste 2

truncate table A;
truncate table B;
truncate table C;
insert A (value) values (1);
insert B (value) values (2);
insert C (value) values (0);

select t7.*
from thing7 t7 
join
(   select A.value as Avalue, B.value as Bvalue, C.value as Cvalue
    from A
    cross join B
    cross join C
    order by a.value,b.value,c.value
) xDerived
on xDerived.Avalue=t7.A and xDerived.Bvalue=t7.B and xDerived.Cvalue=t7.C;
-- no rows returned

Seria muito fácil transformar isso em uma pesquisa baseada em sessão. O conceito que existe é aquele em que os arrays a serem pesquisados ​​(tabelas A B C) possuem uma coluna de sessão. Isso facilitaria o uso simultâneo de vários usuários. Mas isso é excesso de engenharia da resposta, mas pergunte se você deseja mais informações sobre isso.