【问题标题】:Get 20 most frequent pairs(2/2) and triplets(3/3) of numbers获得 20 个最常见的数字对 (2/2) 和三元组 (3/3)
【发布时间】:2016-01-06 15:46:26
【问题描述】:

我正在尝试获取最常见的数字对和三元组 (3/3),我的表格如下所示:

+----+------+------+------+------+------+------+------+------+------+------+
| id | nr1  | nr2  | nr3  | nr4  | nr5  | nr6  | nr7  | nr8  | nr9  | nr10 |
+----+------+------+------+------+------+------+------+------+------+------+
| 1  | 1    | 39   | 19   | 23   | 28   | 80   | 3    | 42   | 60   | 32   |
+----+------+------+------+------+------+------+------+------+------+------+
| 2  | 43   | 18   | 3    | 24   | 29   | 33   | 15   | 1    | 61   | 80   |
+----+------+------+------+------+------+------+------+------+------+------+
| 3  | 11   | 25   | 33   | 2    | 30   | 3    | 1    | 44   | 62   | 78   |
+----+------+------+------+------+------+------+------+------+------+------+

我想知道我所有行中出现频率最高的前 3 个数字对或三组数字。

例子:

1,3(3次)

1,80(2 次)

3,80(2 次) 1,3,80(2次)

我可以尝试按 1、2、3 之类的顺序添加数字,然后从数据库中提取它们,但我想出的脚本仍然很糟糕,需要几个小时才能检查 10000 行

欢迎任何想法.. 非常感谢。

【问题讨论】:

  • 数量是否有任何限制?也许 1 到 100?
  • 是的,它们是 1 到 90
  • 同一行可以有重复值吗?像两个 80 后?
  • 每行不只有唯一的数字。

标签: php mysql


【解决方案1】:

你需要对你的表进行 unpivot,但是 mysql 没有 unpivot 功能所以你可以这样做

SQL Fiddle Demo

CREATE TABLE unpivot
SELECT *
FROM ( 
        SELECT id, nr1 as n_value FROM tuple union all 
        SELECT id, nr2 as n_value FROM tuple union all 
        SELECT id, nr3 as n_value FROM tuple union all 
        SELECT id, nr4 as n_value FROM tuple union all 
        SELECT id, nr5 as n_value FROM tuple union all 
        SELECT id, nr6 as n_value FROM tuple union all 
        SELECT id, nr7 as n_value FROM tuple union all 
        SELECT id, nr8 as n_value FROM tuple union all 
        SELECT id, nr9 as n_value FROM tuple union all 
        SELECT id, nr10 as n_value FROM tuple
     ) as T

现在查找与自身连接的对数。

SELECT n1, n2, count(*) as total
FROM 
    (
    SELECT up1.n_value as n1, up2.n_value as n2
    FROM unpivot up1
    JOIN unpivot up2
      ON up1.`id` = up2.`id`        
     AND up1.n_value < up2.n_value  
   ) T
GROUP BY n1, n2
ORDER BY total desc
LIMIT 3;

对于三胞胎,您可以加入餐桌三次

SELECT n1, n2, n3, count(*) as total
FROM 
    (
    SELECT up1.n_value as n1, up2.n_value as n2, up3.n_value as n3
    FROM unpivot up1
    JOIN unpivot up2
      ON up1.`id` = up2.`id`        
     AND up1.n_value < up2.n_value  
     JOIN unpivot up3
      ON up2.`id` = up3.`id`        
     AND up2.n_value < up3.n_value  
   ) T
GROUP BY n1, n2, n3
ORDER BY total desc
LIMIT 3;

更新:

我在 postgresql 上做了测试

创建 50k 行,随机值从 1 到 90

创建索引后,查询只需 2 秒即可完成。

【讨论】:

  • 感谢您的想法,但我不太了解查询...特别是 SELECT up1.n_value 部分?我在那里出错了
  • 是的,我今天早上进行了测试,一切看起来都很好,但我遇到了同样的问题......当我有 50k 条记录时非常慢:( unpivot 的想法很棒,但仍然很慢。
  • 您是否设置了索引?你能分享explain plan吗??
  • 检查我的更新,我在 postgres 上试了一下,只需要 2 秒
  • 哇!我整晚都想弄清楚该怎么做。似乎我的电脑有问题,因为我在笔记本电脑上尝试过,但 6 小时后仍未完成。我完全按照你展示的那样做,并且需要永远:(
猜你喜欢
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多