【问题标题】:What is the most efficient way to compare rows in a MySQL table with Java用Java比较MySQL表中的行的最有效方法是什么
【发布时间】:2014-11-07 20:45:44
【问题描述】:

这是一个很大程度上是概念性的问题,所以我没有任何代码要显示。我会尽力解释这一点。我正在编写一个程序,该程序应该找到在随机组合的大表中找到的常见数字序列。

所以以这个数据为例:

1 5 3 9 6 3 8 8 3 3

6 7 5 5 5 4 9 2 0 1

6 4 4 3 7 8 3 9 5 6 

2 4 2 4 5 5 3 4 7 7 

1 5 6 3 4 9 9 3 3 2

0 2 7 9 4 5 3 9 8 3

这些是数字 1-9 的随机组合。对于发现不止一次的每 3 位(或更多)序列,我需要将其放入另一个数据库中。所以第一行包含“5 3 9”,第 6 行也包含“5 3 9”。我会将该序列放在一个单独的表中,并附上它被找到的次数。

我仍在研究实际进行这些比较的算法,但我认为我必须从“1 5 3”开始,将其与找到的每个 3 数字三重奏进行比较,然后继续进行“5 3 9” " 然后 "3 9 6" 等等......

我现在的主要问题是,如果这些数字存储在数据库中,我不知道该怎么做。我的数据库表有 11 列。每个单独的数字一列,整个 10 位序列的一列。列称为 Sequence、1stNum、2ndNum、3rdNum...10thNum。

Visual:我的数据库中上述数据的第一行是这样的:

|  1 5 3 9 6 3 8 8 3 3  |  1  |  5  |  3  |  9  |  6  |  3  |  8  |  8  |  3  |  3  |

("|" 分列)

如何有效地使用 Java 进行比较?我多次迭代表中的每一行。对于要比较的初始序列一次,对于这些序列中的每一个,我都会遍历每一行。基本上是for循环中的for循环。这听起来像是要进行大量查询,并且如果表变得很大(它会),则可能需要很长时间。

如果我使用查询遍历数据库,或者我转储数据库并遍历文件,计算效率会更高吗?

我试图尽可能地解释这一点,这对我来说是一个非常混乱的过程。我可以澄清任何你需要我做的事情。我只需要有关最佳行动方案的指导。

【问题讨论】:

  • 为什么你要这样做?难道你不能将全部内容读入一个List并在内存中排序吗?
  • 它是我正在玩的个人编程项目的一部分。细节非常混乱,但我试图通过将其设置为一个独立的问题来解释。不过,我根本没有对其进行排序。
  • @ElliottFrisch 数字的顺序很重要,因此排序会破坏目的。如果这就是你的意思。
  • I'm still working out the algorithm for actually making these comparisons but i figure i'll have to start with "1 5 3", compare that to every single 3 number trio found, then move on to "5 3 9" then "3 9 6" etc.... 不要认为这是个好主意。我宁愿使用 HashSet 来存储每个遇到的三元组。每次发生碰撞时,我都会在 Map 中增加这个三元组的计数器。这样,我认为您会节省大量时间,因为与其他所有三元组相比,插入 HashSet 的成本更低。
  • 比较值的行为有什么作用?你想要最小或最大的序列吗?将其映射到Comparable 3 字段 POJO?

标签: java mysql sql database


【解决方案1】:

假设您已检索到列表中的序列,我会这样做:

List<String> sequences = Arrays.asList("1539638833","6755549201","6443783956","2424553477","1563499332","0279453983");
Map<String,Integer> count = new HashMap<>();
for (String seq : sequences) {
    int length = seq.length();
    for (int i=0 ; i<length - 2 ; i++) {
        String sub = seq.substring(i,i + 3);
        count.put(sub,count.containsKey(sub) ? count.get(sub) + 1 : 1);
    }
}
System.out.println(count);   

输出:

{920=1, 783=1, 945=1, 332=1, 963=1, 644=1, 156=1, 983=1, 453=1, 153=1, 388=1, 534=1,
 455=1, 245=1, 539=2, 554=1, 242=1, 555=1, 553=1, 437=1, 883=1, 349=1, 755=1, 675=1,
 638=1, 395=1, 201=1, 956=1, 933=1, 499=1, 634=1, 839=1, 794=1, 027=1, 477=1, 833=1,
 347=1, 492=1, 378=1, 279=1, 993=1, 443=1, 396=1, 398=1, 549=1, 563=1, 424=1}

然后您可以将这些值从地图存储到数据库中。

【讨论】:

  • 是的,这绝对是其中的一部分。我预见的下一个问题是,在 3 位数之后,我必须转到 4 位数,然后以此类推,但相比之下这似乎更简单。此外,由于这些序列存储在我的数据库中,我想最好的做法是查询一次并将所有序列放入初始列表中吧?
  • 另外,在其中发现的仅有的三个常见数字是“539”,这有点疯狂,我真的期待的不仅仅是一个序列。
  • @RyanBrady :我也认为这将是一种有效的方法。如果您想要 4 位数或任意位数,可以通过对代码稍作更改来完成。最后,总共有 1000 种可能的组合,而您的示例中只有 48 种,因此没有重复的概率非常高。
  • 你不知道我使用它有多兴奋 :) 我没想到会是 11 行代码哈哈。我会玩弄它,但我可能会回来问问题。万分感谢。如果它按预期工作,我会回来并勾选这个答案。
  • @RyanBrady :哈哈,让 Java Collection API 成为您的朋友以提高效率。 HashSetHashMap 真的很有用。你应该阅读他们的文档以及ArrayListLinkedListTreeSet。然后,根据你的需要,还有一些其他有趣的类如ArrayDequePriorityQueue...
【解决方案2】:

你可以在 sql 中用 union 子句做到这一点:

select sum(c), sequence 
from
(   
    select
        count(*) as c, concat(col1 ,col2 , col3) as sequence
        from t
        group by col1, col2, col3
    union
    select
        count(*) as c, concat(col2 ,col3 , col4) as sequence
        from t
        group by col2, col3, col4
    union (... and so on enumerating through the column combinations)
) as tt
group by sequence

我想一个纯 java 实现会更快,更少 内存开销。但是,如果您已经在数据库中拥有它,它可能会很快 够了。

【讨论】:

  • 天哪。我不太擅长构建 SQL 查询,但我什至从未考虑过可以这样做。当您说“col1”,“col2”等时,这些列应该包含各个数字,对吗?你对包含整个 10 位数字序列的列什么都不做?
  • col1 将是您的表的“1stNum”。添加 10 序列列会破坏您的结果,因为分组都是唯一的,除非 10 位数字重复。 group by 子句只能包含您“分组依据”的列。
  • Sql 真的不喜欢它的记录被视为数组。这就是为什么这将是一个非常冗长的查询,因为您不能像在过程语言中那样轻松地索引行。如果您想尝试每种组合,输入会有点乏味,但绝对可行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 2021-04-02
  • 2010-09-06
相关资源
最近更新 更多