缩放列中的值

时间:2011-12-18 20:53:09

标签: mysql sql sql-server

我希望为我的数据做一种特殊的缩放。

是否可以在列中查询具有以下内容的数据库:

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服务器。这种类型的缩放对我的应用程序非常重要,我将在不同的表上使用它。我将在Python3中编程。

修改 SQL Server也是一个选项,以及开源dbs

7 个答案:

答案 0 :(得分:1)

我在理解你的算法时遇到了一些麻烦,但我建议用编程语言来执行这个逻辑。这可能更有效,更容易维护。

答案 1 :(得分: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;
}

答案 2 :(得分: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

答案 3 :(得分:0)

SQL Server,Oracle等可以访问RANK()等分析函数。这些功能使这些问题非常易于管理。我不知道可以做到这一点的开源RDBMS。 (如果您建议您使用的特定RDBMS,并且它可以访问RANK(),我可以告诉您我是如何接近它的。)

如果没有此类分析功能,建议您最好在客户端代码中执行此操作。


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

SELECT x FROM yourTable GROUP BY x ORDER BY x

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

答案 4 :(得分: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

答案 5 :(得分:0)

我认为这应该可行,因为我实际上在本专栏中没有任何0。我该如何优化这个sql server代码?

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

谢谢!

答案 6 :(得分: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