2015-02-07 52 views
0

所以,這是一個挑戰:比賽的兩行之間的數的mysql

我有兩個表:

標準具:

+-----+-----+-----+-----+----+ 
| 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 

我怎樣才能做到這一點?

+0

列包含哪些數據?只有(格式化)號碼?如果是這樣,從什麼範圍? – collapsar 2015-02-07 08:47:37

+0

在列c1,c2,c3,c4,c5中僅格式化的數字範圍從1到10,在e1,e2,e3,e4,e5 - 相同 – Vlad 2015-02-07 21:40:07

回答

0

目的是在主客戶表和客戶表的每一行之間建立最大的部分匹配,而不考慮各自的列標識。

這個想法是通過以另一種方式表示列內容來從列標識抽象出來。如您所示,值域爲{1, ..., 10},您可以選擇前10個素數{p_1, ...,p_10} = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 },將i改爲p_i。比較將基於映射列值的乘積。這種方法利用素數分解的唯一性,即。每個正整數都分解成一組唯一的素數。

一次通過獨立的SQL UPDATE語句是相當麻煩的寫下來,所以我們創建一個包含映射值的產品的臨時表:

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子句,該子句避免了對臨時表的需要。
  • 31ELSE分支中的上述CASE表達式是一個虛擬值。
+0

看來合適,謝謝! – Vlad 2015-02-20 14:04:48