【问题标题】:search MySQL matching n numbers from string of m numbers从 m 个数字的字符串中搜索匹配 n 个数字的 MySQL
【发布时间】:2015-02-18 00:58:03
【问题描述】:

我的 MySQL 数据库中有大约 500 万行与以下系统匹配

n1-n2-n3-n4-n5(例如 8-23-43-12-3),其中每个数字对该序列都是唯一的。此外,每个数字的范围从 1 到 99。

我需要一种方法来检索 MySQL 数据库中五个数字中有三个匹配的所有行。例如,用户输入 4-23-65-82-3,我想返回所有输入的五个数字中任意 3 个的行,所以 4-65-12-49-82 匹配,34-23-76-3-65 匹配等.

我的表如下:

number_table (id , uuid , five_numbers , first_number , second_number , third_number , fourth_number , fifth_number)

到目前为止我所尝试的:

  1. 遍历每一行并匹配任何具有first_number 的行是用户提交的五个数字中的任何一个。这不聪明!

  2. 与 MySQL 中的 RegExp 匹配,但这需要包含所有可能组合的 SQL 语句。这不是太聪明,但是如果有人有更高效的 MySQL REGEXP,我可以使用得很好。

我本质上是在寻找 SQL 解决方案,因为我不必担心内存耗尽,SQL 执行会更快,我想将它放在一个视图中,以便我可以在其上执行一些命令。

我为这篇冗长的帖子道歉,但我想提供尽可能多的信息。

谢谢!

【问题讨论】:

  • 请发布样本数据和预期结果?您如何传递用户提交的数字?也请正确标记您的问题。
  • 您的根本问题是您没有正确规范化您的数据。添加具有行 ID 和数字(每个行 ID 5 行)的两列表将使查询变得相对简单。

标签: php mysql sql-server regex


【解决方案1】:

假设您的用户输入为 n1、n2、n3、n4、n5,您可以编写如下 sql:

select id, uuid, five_numbers from
    (select *, 
        if(first_number in (n1,n2,n3,n4,n5), 1, 0)  +
        if(second_number in (n1,n2,n3,n4,n5), 1, 0) +
        if(third_number in (n1,n2,n3,n4,n5), 1, 0)  +
        if(fourth_number in (n1,n2,n3,n4,n5), 1, 0) +
        if(fifth_number in (n1,n2,n3,n4,n5), 1, 0) as total
     from number_table) as t 
where total >= 3

因此,如果五个数字中的任何一个具有该值,它将在总数中加 1。然后,您可以使用包含 3 个或更多用户输入数字的数字过滤您的行

【讨论】:

  • 这是一个非常好的方法,因为数字在集合中必须是唯一的。
【解决方案2】:

快速回答是:

SELECT * FROM 
(SELECT *,
 five_numbers REGEXP '^3-|-3-|-3$' as n1,
 five_numbers REGEXP '65' as n2,
 five_numbers REGEXP '82' as n3 
FROM `number_table`) as t 
WHERE t.n1+t.n2+t.n3=3

如果你需要我可以用 PDO 设置 php 代码,请问

【讨论】:

    【解决方案3】:

    MySQL FIELD 函数在这里很有用:

    SELECT id, uuid, five_numbers, 
    FIELD(A, first_number , second_number , third_number , fourth_number , fifth_number) > 0 as aFound,
    FIELD(B, first_number , second_number , third_number , fourth_number , fifth_number) > 0 as bFound,
    FIELD(C, first_number , second_number , third_number , fourth_number , fifth_number) > 0 as cFound,
    FIELD(D, first_number , second_number , third_number , fourth_number , fifth_number) > 0 as dFound,
    FIELD(E, first_number , second_number , third_number , fourth_number , fifth_number) > 0 as eFound
    FROM number_table
    WHERE
    (
    first_number in (A, B, C, D, E)
    OR second_number in (A, B, C, D, E)
    OR third_number in (A, B, C, D, E)
    )
    AND aFound + bFound + cFound + dFound + eFound >= 3;
    

    FIELD 函数返回它找到第一个参数的参数的索引,或者返回 0。如果您选择 (n > 0) 作为参数,它会解析为 TRUE,MySQL 将其视为整数值的1。因此,您可以将它们加在一起以检查值,而无需执行子查询。您可以通过对各个字段进行“输入”检查来获得一些额外的性能,因此您不必针对整个表行集计算函数值。不过,您只需检查前三个字段,因为如果它至少没有匹配其中一个,则不可能匹配五个数字中的三个。

    应该也可以简单地选择

    SELECT * 
    FROM number_table
    WHERE
    ((LOCATE(A, five_numbers) > 0) +
    (LOCATE(B, five_numbers) > 0) +
    (LOCATE(C, five_numbers) > 0) +
    (LOCATE(D, five_numbers) > 0) +
    (LOCATE(E, five_numbers) > 0)) >= 3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-01
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多