2011-12-18 20 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