mysql - mysql 两行之间的匹配数

标签 mysql numbers

所以,这就是挑战:

我有两个表:

标准具:

+-----+-----+-----+-----+----+
|  e1 |  e2 |  e3 |  e4 | e5 |
+-----+-----+-----+-----+----+
|  01 |  02 |  03 |  04 | 05 |
+-----+-----+-----+-----+----+

候选人:

+-----+----+-----+-----+-----+----+----+
| ID  | c1 | c2  | c3  | c4  | c5 | nn |
+-----+----+-----+-----+-----+----+----+
| 00  | 03 | 08  | 02  | 01  | 06 | ** |
+-----+----+-----+-----+-----+----+----+
| 01  | 05 | 04  | 03  | 02  | 01 | ** |
+-----+----+-----+-----+-----+----+----+
| 02  | 06 | 07  | 08  | 09  | 10 | ** |
+-----+----+-----+-----+-----+----+----+
| 03  | 08 | 06  | 09  | 02  | 07 | ** |
+-----+----+-----+-----+-----+----+----+

我应该使用什么请求来查找并保存(在 nn 列中)每行的两行(e1、e2、e3、e4、e5 和 c1、c2、c3、c4、c5)之间的匹配数表候选者?

应该是下一个结果:

候选人:

|-----|----|-----|-----|-----|-----|----|
| ID  | c1 | c2  | c3  | c4  | c5  | nn |
|-----|----|-----|-----|-----|-----|----|
| 00  | 03 | 08  | 02  | 01  | 06  | 03 |
|-----|----|-----|-----|-----|-----|----|
| 01  | 05 | 04  | 03  | 02  | 01  | 05 |
|-----|----|-----|-----|-----|-----|----|
| 02  | 06 | 07  | 08  | 09  | 10  | 00 |
|-----|----|-----|-----|-----|-----|----|
| 03  | 08 | 06  | 09  | 02  | 07  | 01 |
|-----|----|-----|-----|-----|-----|----|

nn 的结果是:

0 - no matches
1,2,3,4,5 - numbers of matches 

我怎样才能实现这一目标?

最佳答案

目标是在主行和客户端表的每一行之间建立最大部分匹配,而不考虑各自的列标识。

这个想法是通过以另一种方式表示列内容来从列 ID 中抽象出来。正如您所指出的,值域是 {1, ..., 10},可以选择前 10 个素数 {p_1, ...,p_10} = { 2, 3 , 5, 7, 11, 13, 17, 19, 23, 29 },将 i 映射到 p_i。比较将基于映射列值的乘积。这种方法利用了素因数分解的独特性,即。每个正整数都分解为唯一的多组素数。

一次性独立sql更新语句写起来相当麻烦,因此我们创建一个临时表来包含映射值的乘积:

CREATE TEMPORARY TABLE t_pp (
      id            NUMBER
    , mp_candidates NUMBER
    , mp_etalon     NUMBER
    , nn            NUMBER
);
INSERT INTO t_pp ( id, mp_candidates, mp_etalon )
     SELECT id
          ,   CASE c1
                  WHEN  1 THEN  2
                  WHEN  2 THEN  3
                  WHEN  3 THEN  5
                  WHEN  4 THEN  7
                  WHEN  5 THEN 11
                  WHEN  6 THEN 13
                  WHEN  7 THEN 17
                  WHEN  8 THEN 19
                  WHEN  9 THEN 23
                  WHEN 10 THEN 29
                  ELSE         31
              END
            * CASE c2 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
            * CASE c3 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
            * CASE c4 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
            * CASE c5 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
                mp_candidates

          ,   CASE e1
                  WHEN  1 THEN  2
                  WHEN  2 THEN  3
                  WHEN  3 THEN  5
                  WHEN  4 THEN  7
                  WHEN  5 THEN 11
                  WHEN  6 THEN 13
                  WHEN  7 THEN 17
                  WHEN  8 THEN 19
                  WHEN  9 THEN 23
                  WHEN 10 THEN 29
                  ELSE         31
              END
            * CASE e2 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
            * CASE e3 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
            * CASE e4 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
            * CASE e5 WHEN  2 THEN  3 WHEN  3 THEN  5 WHEN  4 THEN  7 WHEN  5 THEN 11 WHEN  6 THEN 13 WHEN  7 THEN 17 WHEN  8 THEN 19 WHEN  9 THEN 23 WHEN 10 THEN 29 ELSE 31 END
                mp_etalon
          , 0   nn
       FROM candidates
 CROSS JOIN etalon     
          ;

现在进行第 2 遍 - 计算匹配数:

UPDATE t_pp
   SET nn =
             CASE WHEN mp_candidates MOD  2 = 0 AND mp_etalon MOD  2 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD  3 = 0 AND mp_etalon MOD  3 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD  5 = 0 AND mp_etalon MOD  5 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD  7 = 0 AND mp_etalon MOD  7 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD 11 = 0 AND mp_etalon MOD 11 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD 13 = 0 AND mp_etalon MOD 13 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD 17 = 0 AND mp_etalon MOD 17 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD 19 = 0 AND mp_etalon MOD 19 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD 23 = 0 AND mp_etalon MOD 23 = 0  THEN 1 ELSE 0 END
           + CASE WHEN mp_candidates MOD 29 = 0 AND mp_etalon MOD 29 = 0  THEN 1 ELSE 0 END
     ;

最后,将结果转移到原表并进行清理:

UPDATE candidates c
   set nn = ( SELECT p.nn FROM t_pp p WHERE p.id = c.id )
     ;
DELETE TEMPORARY TABLE t_pp;

更多注意事项:

  • 所示方案假定每行中的单元格值都是唯一的。但是,它可以轻松扩展以允许值多次出现。
  • 原则上,这可以封装在单个 sql 语句中 - 出于显而易见的原因,不建议这样做。
  • 除 mysql 之外的 Rdbms 遵循 sql 标准并提供 WITH 子句,从而无需使用临时表。
  • 上述 CASE 表达式的 ELSE 分支中的值 31 是一个虚拟值。

关于mysql - mysql 两行之间的匹配数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28380180/

相关文章:

math - 计算大数最快的编程语言?

mysql - 将 BIGINT UNSIGNED 转换为 INT

algorithm - 这可能吗?总和的最后几位等于另一个数字

c - 线程和并行编程

php - is_numeric() 与 is_float() 与 is_int()

c# - 按数字对字符串列表进行排序(1,2,...,9,10 而不是 1,10,2)

mysql - 是否允许在 MySQL 中使用数字作为表名?

MYSQL 导入转储完成但有错误

mysql - Percona Cluster - 主节点失败,如何进行

MySQL更新子选择问题