代码之家  ›  专栏  ›  技术社区  ›  DataWarrior Niño

检查MySQL行中是否出现了项集

  •  1
  • DataWarrior Niño  · 技术社区  · 7 年前

    我正在MySQL(结合Java)中处理大型数据集,并尝试实现一个频繁项集算法。 该算法的一个经常性方面是计算一组项目(一个项目是一个随机整数)在数据集中出现的次数。

    以这个小数据集为例 T :

    ID | COL1 | COL2 | COL3 | COL4 | COL5 |
    ---------------------------------------
    1  |   8  |  35  |  42  |  12  |  27  |
    2  |  22  |  42  |  35  |  8   | NULL |
    3  |  18  |  22  |   8  | NULL | NULL |
    4  |  42  |  12  |  27  |  35  |  8   |
    5  |  18  |  27  |  12  |  22  | NULL |
    

    还有这张桌子 T2级 :

    COL1 | COL2 |
    -------------
    35   | 27   |
    22   | 8    |
    42   | 8    |
    18   | 35   |
    35   | 42   |
    

    我想要的结果是下表(也可以是查询的答案):

    COL1 | COL2 | COUNT |
    ---------------------
    35   | 27   | 2     |
    22   | 8    | 2     |
    42   | 8    | 3     |
    18   | 35   | 0     |
    35   | 42   | 3     |
    

    所以我想计算表中每一行的每一次出现次数 T2级 在表中 T 。基本上一排 T2级 中的行子集 T

    这必须在算法的每一代中完成。这是一个很小的例子,最终也必须这样做 T3 (包含3项的行), T4类 (包含4项的行)等表格 T 保持不变。 我还必须考虑到顺序无关紧要(| 35,27 |=| 27,35 |),而且它们可能不会在 T

    是否可以在不太多次检查数据集的情况下执行此操作(而 太多了 =大于中的行数 T2级 )? 将一行表示为一个元组(例如,(35,27))是否更好,以便它成为一个项目?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Uueerdo    7 年前

    如果您可以将数据重组为每行一个值,对于T和TN,类似的内容应该可以同时用于所有TN。

    SELECT n_id, COUNT(CASE WHEN matches = n_count THEN v_id ELSE NULL) AS occurences
    FROM (
      SELECT n.n_id, v.set_id AS v_id, n.n_count, COUNT(*) AS matches
      FROM (SELECT n_id, COUNT(*) AS n_count FROM tN GROUP BY id) AS n
      INNER JOIN tN AS nv ON n.n_id = nv.n_id
      LEFT JOIN T_VALUES AS v ON nv.value = v.value
      GROUP BY n.n_id, v.set_id, n.n_count
    ) AS subQ;
    

    如果您需要在最终结果中使用TN值,类似这样的结果很接近。

    SELECT n_id, n_values, COUNT(CASE WHEN matches = n_count THEN v_id ELSE NULL) AS occurences
    FROM (
      SELECT n.n_id, n.n_count, n.n_values, v.set_id AS v_id, COUNT(*) AS matches
      FROM (
           SELECT n_id, COUNT(*) AS n_count 
              , GROUP_CONCAT(n.value) AS n_values
           FROM tN 
           GROUP BY id
      ) AS n
      INNER JOIN tN AS nv ON n.n_id = nv.n_id
      LEFT JOIN T_VALUES AS v ON nv.value = v.value
      GROUP BY n.n_id, n.n_count, n.n_values, v.set_id
    ) AS subQ;
    

    注意:您可能不需要子查询,但最终可能会让数据库为T的每一行重复计算相同的n\u计数和n\u值。

        2
  •  0
  •   DataWarrior Niño    7 年前

    由于Uueerdo的回答,我意识到我必须使用不同的结构,所以我没有使用表 T :

    ID | COL1 | COL2 | COL3 | COL4 | COL5 |
    ---------------------------------------
    1  |   8  |  35  |  42  |  12  |  27  |
    2  |  22  |  42  |  35  |  8   | NULL |
    3  |  18  |  22  |   8  | NULL | NULL |
    4  |  42  |  12  |  27  |  35  |  8   |
    5  |  18  |  27  |  12  |  22  | NULL |
    

    我现在使用 t新建 :

    ID | Item|
    1  | 8   |
    1  | 35  |
    1  | 42  |
    .  |  .  |
    .  |  .  |
    .  |  .  |
    

    这在SQL中更容易实现,您可以使用Group By和Join来获得所需的结果。该查询可用于具有相同ID的任意数量的项。此外,您不必使用NULL值,而且数据集更容易创建

    如果有人想知道我最终使用的查询,请让我知道(要想得到好的表名并使其清晰易懂,需要做一些工作)。