加入两个不同的mySQL表的最佳方法 - 从python规划django

时间:2009-12-01 14:52:04

标签: python mysql django django-models

table a (t_a):
id  name    last    first   email           state   country
0   sklass  klass   steve   sklass@foo.com  in      uk
1   jabid   abid    john    abid@foo.com    ny      us
2   jcolle  colle   john    jcolle@foo.com  wi      us


table b (t_b):
id  sn      given   nick    email           l   c   
0   steven  klass   steve   sklass@foo.com  in  uk
1   john    abid    -       abid_j@foo.com  ny  us
2   johnny  colle   john    jcolle@foo.com  wi  us
3   john    abid    -       abid@foo.com    ny  us

上面列出的是(缩写的)列和行mySQL表。看看这两个表格,很明显,通过严格查看值(未查看id)并比较匹配的值数量,您将得到这些值匹配。

t_a     t_b
0       0
1       3
2       2
-       1

我最终要做的是在Django中这样做 - 我不确定这是否重要。在过去,我使用纯python完成了这个操作,在其中我销毁旧数据并创建三个新表。我想转移我的实施(下面列出),因为我看到的问题是时间改变了事情,人们来去匆匆。过去我刚刚重新生成数据 - 但现在我想跟踪人们离开的时间,而不是简单地替换(删除)数据。我相信通过SQL更新更优雅并保留历史。

我想知道如何直接从mySQL(SQL函数或新表的构造)获得这个合并的答案,它以下列方式合并数据。我想用纯SQL做这个(我相信我可以在Django中做到这一点)。所以我正在寻找符合以下标准的解决方案:

  1. 有一个min_match,它定义了两行之间必须对齐的最小匹配数才能被视为有效。
  2. 虽然表可能具有不同的长度,但它是1对1的映射。换句话说,许多人可能不会发生(还)
  3. 现在我的背景是python,对我来说,最简单的方法就是在两个表中较短的一个上执行for循环,然后在另一个表中查看匹配数量的for循环。在代码中,这看起来像这样。

    t_a = [ ["sklass", "klass", "steve", "sklass@foo.com", "in", "uk", ],
            ["jabid", "abid", "john", "abid@foo.com", "ny", "us", ],
            ["jcolle", "colle", "john", "jcolle@foo.com", "wi", "us", ], ]
    
    t_b = [ ["steven", "klass", "steve", "sklass@foo.com", "in", "uk",],
            ["john", "abid", "abid_j@foo.com", "ny", "us",],
            ["johnny", "colle", "john", "jcolle@foo.com", "wi", "us",],
            ["john", "abid", "abid@foo.com", "ny", "us",], ]
    
    min_match = 3
    
    for person_a in t_a:
        match = 0
        match_pct = 0.0
        match_a_index = t_a.index(person_a)
        for person_b in t_b:
            new_match_count = len(list(set(person_a) & set(person_b)))
            if new_match_count > match:
                match = new_match_count
                match_b_index = t_b.index(person_b)
                match_pct = "%.2f" % (float(new_match_count) / \
                  float(len(set(person_a + person_b))) * 100)
        if match >= min_match:
            print match_a_index, match_b_index #, match_pct, match
    

    评论提出问题为什么不加入电子邮件地址。我不一定知道列中的值会匹配。我确定来自t_a中给定行的值将匹配t_b中行的值。我希望t_a到t_b中给定行的最高(最可能)匹配,并且只有当匹配数高于min_match时才会匹配。

1 个答案:

答案 0 :(得分:1)

您可以通过存储过程执行的游标直接在MySQL中执行此操作。

DELIMITER $$
CREATE PROCEDURE `proc_name`()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE a_id BIGINT UNSIGNED;
  DECLARE b_id BIGINT UNSIGNED;
  DECLARE x_count INT;

  -- something like the following
  DECLARE cur1 CURSOR FOR SELECT t_a.id, t_b.id FROM t_a, t_b WHERE t_a.email = t_b.email;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  SELECT COUNT(*) INTO x_count FROM t_a, t_b WHERE t_a.email = t_b.email;

  IF(x_count > <some_min_value>) THEN

    OPEN cur1;

    REPEAT
      FETCH cur1 INTO a_id, b_id;
      IF NOT done THEN

        -- do something here like update rows, remove rows, etc.
        -- a_id and b_id hold the two id values for the two tables which
        -- I assume to be primary keys

      END IF;
    UNTIL done END REPEAT;

    CLOSE cur1;

  END IF;
END
$$