列の値のスケーリング

私は私のデータのために特別なタイプのスケーリングをしたいと思っています。

列内に次のintを持つデータベースを照会することは可能ですか?

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でプログラミングします。

EDIT: SQL Server is also an option, as well as open source dbs

1
クライアント側で簡単に行うことはできますが、SQL Serverを使用すると、私の計画は 1/COUNT(DISTINCT ID)を取得してSet値を取得し、ランキング機能を使用して値をIDに設定します。 MySQLにも同様の機能があるかどうかはわかりません。
追加された 著者 Lieven Keersmaekers,
このSQL Serverにタグを付けましたが、それは非常にオープンソースではありません...
追加された 著者 MatBailie,
ああ、MySQLはランキング機能をサポートしました!
追加された 著者 Andriy M,

7 答え

私は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;
}
1
追加された
良いキャッチ!一定。
追加された 著者 Tomas,
PHPは私のカップではありませんが、配列全体の数を計算して増分を計算しているようです。代わりに別個の値の数を取る必要があります。
追加された 著者 Lieven Keersmaekers,

私はあなたのアルゴリズムを理解するいくつかの問題を抱えているが、私はプログラミング言語でこのロジックを実行することをお勧めします。おそらくもっと効率的で、維持しやすいでしょう。

1
追加された
10は5よりも重要ですが、私の場合は2倍ではないので、私が使用しているスケーリングのタイプです。
追加された 著者 Baz,

私は実際にこの列に0がないので、これはうまくいくと思います。このSQL Serverコードを最適化するにはどうすればよいですか?

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

ありがとう!

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
追加された

SQL Server、Oracleなどは、RANK()などの分析関数にアクセスできます。これらの機能は、このような問題を非常に扱いやすくします。私はこれを行うことができるオープンソースのRDBMSを認識していません。 (あなたが使用している特定のRDBMSについてアドバイスをしていて、RANK()へのアクセス権がある場合は、どのようにアプローチすればよいかを示すことができます)。

このような分析機能がなければ、クライアントコードでこれを行うことをお勧めします。


まず、何個の異なる価値があるか、それが何であるかを知る必要があります。

SELECT x FROM yourTable GROUP BY x ORDER BY x

これらの値の配列を取得したら、簡単なルックアップです。結果セットの各要素について、ルックアップテーブル内の値の位置を確認します。それであなたの結果があります。

0
追加された
SQL Serverにアクセスできます。
追加された 著者 Baz,

実行可能な発音をする前に、これを良いテストをしてください:

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ソリューションです。セッション変数がこのタイプのクエリを少し簡単にするので、私はこれを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
0
追加された