繁体   English   中英

PHP MySQL用于MySQL表的排列

[英]PHP MySQL for permutations on MySQL Table

我有一个包含7列的mysql表,每行包含整数值。

我有一个简单的站点,它接收用户的值,我必须尝试查看用户发送的值是否匹配或类似于表中的任何行。

因此用户将例如1 2 3 4 5 6 7为输入。

我必须找出我的表中的任何行是否与它没有顺序相似。 所以1 2 3 4 5 6 7 = 7 6 5 4 3 2 1等等。 该表包含超过40,000行数据。

我还必须看到,如果它们共享至少567中共同的数字。

这意味着使用排列来查找所有可能的组合。 然而,这种问题的最佳方法是什么?

  1. 从用户那里获取输入并获得所有排列并匹配第一行,第二行等,并报告是否找到? 或者,反过来,从表中获取一行并获得所有排列并根据用户输入进行匹配?

  2. 当有如此多的排列这么大的表时,内存和CPU使用情况怎么样?

在完全规范化的模式中,这是一个具有查询的单个模式

让我们假设您的表与pk为:

create table T1 
( pk char (1), a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int);

insert into T1 values 
('a',1,2,3,4,5,6,7),
('b',2,3,4,5,6,7,8),
('z',10,11,12,13,14,15,16);

这时,我们可以将数据规范化为:

select
   pk, 
   case a
    when 1 then a1
    when 2 then a2
    when 3 then a3
    when 4 then a4
    when 5 then a5
    when 6 then a6
    when 7 then a7
   end
   as v
from T1   
cross join 
   (select 1 as a from dual union all
    select 2 as a from dual union all
    select 3 as a from dual union all
    select 4 as a from dual union all
    select 5 as a from dual union all
    select 6 as a from dual union all
    select 7 as a from dual ) T2

在上一个查询中,您可以轻松地将您的需求与单个匹配:

select pk
from
(
select
   pk, 
   case a
    when 1 then a1
    when 2 then a2
    when 3 then a3
    when 4 then a4
    when 5 then a5
    when 6 then a6
    when 7 then a7
   end
   as v
from T1   
cross join 
   (select 1 as a from dual union all
    select 2 as a from dual union all
    select 3 as a from dual union all
    select 4 as a from dual union all
    select 5 as a from dual union all
    select 6 as a from dual union all
    select 7 as a from dual ) T2
) T
where
   T.v in ( 4,5,6,7,8,9,10)
group by pk
having                                           <-- The Having
   count( pk ) > 4

结果

| PK |
------
|  b |

轻量级方法可能是在数据库中添加一个额外的字段,这是所有7个字段组合的数字排序版本。

例如。 如果数据库中的数据是2 4 7 6 5 1 3,则组合字段将是1234567

然后在比较时,以数字方式对用户响应进行排序,并与数据库中的组合字段进行比较。

根据您的工作情况,您可以像这样编写查询

select * from table where combination like '12%' or combination like '123%' 

如果您知道需要的最小匹配数量,那将会减轻查询的负担

找出他们写的与数据库中的内容有多相似。 你可以使用levenshtein PHP函数: http ://php.net/manual/en/function.levenshtein.php

$result = levenshtein($input,$combination);

我担心你不能真正有效地建立这样的问题查询。

您可以构建WHERE子句,如:

(`1` IN ARRAY(1,2,3,4,5,6,7) 
    AND `2` IN ARRAY(1,2,3,4,5,6,7)
    AND `3` IN ARRAY(1,2,3,4,5,6,7)
    AND `4` IN ARRAY(1,2,3,4,5,6,7)
    AND `5` IN ARRAY(1,2,3,4,5,6,7))
OR
(`1` IN ARRAY(1,2,3,4,5,6,7) 
    AND `2` IN ARRAY(1,2,3,4,5,6,7)
    AND `3` IN ARRAY(1,2,3,4,5,6,7)
    AND `4` IN ARRAY(1,2,3,4,5,6,7)
    AND `6` IN ARRAY(1,2,3,4,5,6,7))
-- Each combination

但这将是一个条件的地狱。 另一方面,您可以尝试使用以下组合:

首先检查第1列是否包含信息:

IF( `1` IN ARRAY(1,2,3,4,5,6,7), 1, 0)

然后总结所有这些数据:

SELECT (
    IF( `1` IN ARRAY(1,2,3,4,5,6,7), 1, 0) +
    IF( `2` IN ARRAY(1,2,3,4,5,6,7), 1, 0) +
    IF( `3` IN ARRAY(1,2,3,4,5,6,7), 1, 0) +
    IF( `4` IN ARRAY(1,2,3,4,5,6,7), 1, 0) +
    IF( `5` IN ARRAY(1,2,3,4,5,6,7), 1, 0) +
    IF( `6` IN ARRAY(1,2,3,4,5,6,7), 1, 0) +
    IF( `7` IN ARRAY(1,2,3,4,5,6,7), 1, 0)
) AS `matches_cnt`
FROM t1
HAVING `matches_cnt` >= 5

这将遍历所有行并且条件非常复杂(因此床性能)。

您也可以尝试用二进制字符串替换值,例如:

1,2,7 = 01000011

然后计算检查记录和数据库之间的汉明距离 ,但这只会降低条件的复杂性,但需要迭代通过所有记录将保持不变。

使用mysql实现:

将替换第一部分:

SELECT (
    $MAX_NUMBER$ - BIT_COUNT( XOR( `binary_representation`, $DATA_FROM_USER$))
) AS `matches_cnt`

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM