2011-12-18 76 views
1

我希望对数据进行特殊类型的缩放。在列中缩放值

是否可以查询它具有以下整数列中的一个数据库:

10 
5 
5 
3 
1 
1 
0 
1 
5 
2 
2 

,并通过查询产生如下表示:

1.0 
0.8 
0.8 
0.6 
0.2 
0.2 
0.0 
1.0 
0.8 
0.4 
0.4 

因此,最大值为1.0和0保持为0.然后我们有一组唯一的值,不包括0,即10,5,3,2,1。这个集合的长度是5.倒数是0.2。然后,我们列5中的下一个最大值变为1-0.2 = 0.8。然后下一个最大值3变为0.8-0.2 = 0.6,依此类推。

10->1.0, 5->0.8, 3->0.6, 2->0.4, 1->0.2, 0->0 

或者你会推荐执行查询的编程语言应该执行此缩放。

我是唯一一个会查询数据库的人,我还没有选择我的数据库,但会使用开源或SQL-Server。这种类型的缩放对于我的应用程序非常重要,我将在不同的表格上使用它。我将在Python3中进行编程。

编辑: SQL服务器也是一个选择,还有我有一些很难理解你的算法开源DBS

+0

哦,MySQL的支持排名的功能! – 2011-12-18 21:03:56

+0

在客户端可能比较容易,但使用SQL Server,我的攻击计划是让'1/COUNT(DISTINCT ID)'得到一个Set值并使用一个排序函数将一个Set值附加到ID。我不知道MySQL是否有类似的功能。 – 2011-12-18 21:04:38

+0

你已经标记了这个SQL服务器,但这是非常不开放源代码... – MatBailie 2011-12-18 22:13:47

回答

1

我建议PHP:

$myColumnArray = /* load mysql values here */; 
// order numbers smallest to largest 
$uniqueElements = sort(array_unique($myColumnArray)); 
// calculate increment 
$incriment = count($uniqueElements); 
// go thru elements in orig array and replace with weighted value 
foreach($myColumnArray as &$val){ 
    // get position of element (i.e. "4th largest") 
    $position = array_search ($val, $uniqueElements); 
    // set it equal to weighted value 
    $val = $position * $increment; 
} 
+0

PHP不是我的杯子,但它看起来像是在整个数组中计算一个增量。您应该改用不同值的数量。 – 2011-12-18 21:07:41

+0

好赶上!固定。 – Tomas 2011-12-18 21:08:30

1

,但我会建议在编程语言执行此逻辑。这可能更有效,更容易维护。

+0

10比5更重要,但在我的情况下不重要两倍,因此我使用的缩放类型。 – Baz 2011-12-18 21:25:43

0

请宣告它可行之前给一个很好的测试:

SELECT 
    Value, 
    rnk/cnt AS WhatYouCallIt 
FROM (
    SELECT 
    @rank := @rank + (t.Value <> @prev) AS rnk, 
    @prev := t.Value AS Value, 
    m.cnt 
    FROM atable t, 
    (SELECT COUNT(DISTINCT Value) AS cnt FROM atable WHERE Value > 0) m 
    (SELECT @prev := 0, @rank = 0) x 
    WHERE t.Value >= 0 
) s 
0

SQL服务器,Oracle等,有机会获得的分析功能,如RANK( )。这些功能使这些问题非常易于管理。我不知道可以做到这一点的开源RDBMS。 (如果您建议您使用的是特定的RDBMS,并且它可以访问RANK(),那么我可以告诉您如何处理它。)

没有这样的分析功能,最好建议您这在你的客户端代码中。


首先,你需要知道有多少不同的值有,它们是什么。

SELECT x FROM yourTable GROUP BY x ORDER BY x 

一旦你有这些值的数组,这是一个简单的查找。对于结果集中的每个元素,检查值在查找表中占据的位置。然后你有你的结果。

+0

我有权访问SQL-Server。 – Baz 2011-12-19 16:03:43

0

纯SQL的尝试 - 无需解析函数:

SELECT 
     t.col    AS oldvalue 
    , tr.rank/tc.cnt AS newvalue 
FROM 
     tableX AS t 
    JOIN 
     (SELECT 
       t1.col 
       , COUNT(*) - 1 AS rank 
      FROM 
        (SELECT DISTINCT col 
        FROM tableX 
       ) AS t1 
       JOIN 
        (SELECT DISTINCT col 
        FROM tableX 
       ) AS t2 
       ON t2.col <= t1.col 
      GROUP BY t1.col 
     ) AS tr 
     ON tr.col = t.col 
    CROSS JOIN 
     (SELECT COUNT(DISTINCT col) - 1 AS cnt 
      FROM tableX 
     ) AS tc 
0

我认为这应该工作,我居然没有在此列中的任何0。我怎样才能优化这个SQL Server代码?

SELECT 
count, 
dense_rank() over(order by count)/CONVERT (float, (SELECT COUNT(DISTINCT count) FROM db)) 
FROM db 

谢谢!

0

纯粹的SQL解决方案。我会为此建议MySQL,因为会话变量使这种类型的查询更容易一些。

SELECT 
    t.id AS 'original_value', 
    IF(st.rank IS NULL, 0.0, ((1.0/st3.group_size) * (st3.group_size - st.rank + 1))) AS 'adjusted_values' 
FROM 
    test t 
LEFT JOIN (
    SELECT 
    st1.id AS 'value', 
    @rank := @rank + 1 AS 'rank' 
    FROM 
    (SELECT @rank := 0) vars, 
    (SELECT DISTINCT id FROM test WHERE id <> 0 ORDER BY id DESC) st1) st ON t.id = st.value 
INNER JOIN (
    SELECT 
     1 AS 'group_by', 
     COUNT(*) AS 'group_size' 
    FROM 
     (SELECT DISTINCT id FROM test WHERE id <> 0 ORDER BY id DESC) st2 
    GROUP BY group_by) st3; 

与您输入它会产生:

original_value adjusted_values 
-------------- --------------- 
0     0 
1     0.2 
2     0.4 
3     0.6 
5     0.8 
10     1 
5     0.8 
1     0.2 
1     0.2 
5     0.8 
2     0.4