在N + M个数字组中找到N个相似数字的组

时间:2015-06-23 18:17:50

标签: sql algorithm

我试图从数组中找到类似的值 - 不只是一个,而是一组,而它们的元素差异的总和是最低的可能值

实施例

0 2 4 6 8 9 11 15 16 19

选择5个数字

结果:

4 6 8 9 11

2 4 6 8 9

两组的元素差异之和为7。

问题是我需要从2927个数字的数组中选择这样的1500个数字组,我不确定算法是否采用0-1500(索引)数组并对差异求和,然后进行i + 1直到它到达1427-2927组是有效的(最后我会检查最小的总和它属于哪个组。)

请注意,这些数字是排序的(无论ASC还是DESC都无关紧要),我正在尝试使用PostgreSQL。

提前致谢。

3 个答案:

答案 0 :(得分:1)

SQL Fiddle

PostgreSQL 9.3架构设置

随机数据的小型数据集:

CREATE TABLE test (
  id INT,
  population INT
);
INSERT INTO TEST VALUES (  1, 12 );
INSERT INTO TEST VALUES (  2, 11 );
INSERT INTO TEST VALUES (  3, 14 );
INSERT INTO TEST VALUES (  4,  6 );
INSERT INTO TEST VALUES (  5,  7 );
INSERT INTO TEST VALUES (  6,  7 );
INSERT INTO TEST VALUES (  7,  1 );
INSERT INTO TEST VALUES (  8, 15 );
INSERT INTO TEST VALUES (  9, 14 );
INSERT INTO TEST VALUES ( 10, 14 );
INSERT INTO TEST VALUES ( 11, 15 );
INSERT INTO TEST VALUES ( 12, 12 );
INSERT INTO TEST VALUES ( 13, 11 );
INSERT INTO TEST VALUES ( 14,  3 );
INSERT INTO TEST VALUES ( 15,  8 );
INSERT INTO TEST VALUES ( 16,  1 );
INSERT INTO TEST VALUES ( 17,  1 );
INSERT INTO TEST VALUES ( 18,  2 );
INSERT INTO TEST VALUES ( 19,  3 );
INSERT INTO TEST VALUES ( 20,  5 );

查询1

WITH ordered_sums AS (
  SELECT ID,
         POPULATION,
         ROW_NUMBER() OVER ( ORDER BY POPULATION ) AS RN,
         POPULATION - LAG(POPULATION,4) OVER ( ORDER BY POPULATION ) AS DIFFERENCE
  FROM   test
), minimum_rn AS (
  SELECT DISTINCT FIRST_VALUE( RN ) OVER wnd AS optimal_rn
  FROM   ordered_sums
  WINDOW wnd AS ( ORDER BY DIFFERENCE )
)
SELECT ID,
       POPULATION
FROM   ordered_sums o
       INNER JOIN
       minimum_rn m
       ON ( o.RN BETWEEN m.OPTIMAL_RN - 4 AND m.OPTIMAL_RN )

<强> Results

| id | population |
|----|------------|
| 10 |         14 |
|  9 |         14 |
|  3 |         14 |
| 11 |         15 |
|  8 |         15 |

上面的查询会选择5行 - 要将其更改为选择N行,然后更改4功能中的LAG和最后一行N-1 {1}}。

答案 1 :(得分:0)

假设列表为a[1]a[2],...,a[N+M]

  1. 计算a[i+M-1]-a[i]i=1的{​​{1}}的最小值。
  2. 达到最小值的N+1的值是i个连续数字的第一个索引,其中元素差异的总和最小。
  3. 理解这种算法的一个关键观察是,排序整数序列的“元素差异之和”只是第一个和最后一个元素之间的差异。例如。对于M,它是4 6 8 9 11

答案 2 :(得分:0)

此解决方案应该有效。 Row_number()获取订单。自我加入+1499,然后根据对中的大小差异排序。

DECLARE @cities TABLE (
    city VARCHAR(512)
    ,size INT
    ,rownum INT
    )

INSERT INTO @cities
SELECT *
    ,row_number() OVER (
        ORDER BY size
        ) rownum
FROM 
    rawdata

SELECT *
    ,d.size - c.size difference
FROM @cities c
INNER JOIN @cities d ON c.rownum + 1499 = d.rownum
WHERE c.rownum <=2927-1499
ORDER BY d.size - c.size