2011-08-16 10 views
1

我有一種情況,即在兩個表之間執行連接,並且我需要一個表中的值用作連接中子查詢的LIMIT因子。假設我有以下[極度簡化]表 -執行連接時使用表列值作爲LIMIT

data: 

experiment_id | value 
--------------|-------- 
     1  | 2.5 
     1  | 2.6 
     1  | 4.5 
     1  | 2.3 
     1  | 3.5 
     1  | 2.8 
     2  | 2.3 
     2  | 1.2 
     2  | 1.1 
     2  | 3.6 
     2  | 3.8 
     2  | 4.1 
     2  | 7.9 
     2  | 4.2 
     2  | 1.0 


data_clip: 

experiment_id | clip_index 
--------------|------------ 
     1  |  3 
     2  |  5 

我需要總結每個實驗的分類值達到一定clip_index,實驗之間的變化。所以,我的成績表將非常類似於:

results: 
experiment_id | sum 
--------------|------- 
     1  | 7.6 # => 2.3 + 2.5 + 2.8 
     2  | 13.0 # => 1.0 + 1.1 + 1.2 + 2.3 + 3.6 + 3.8 

通常情況下,我會做這種計算與一些客戶端腳本(紅寶石,蟒蛇等),但我想嘗試在數據庫級別做這個。有些虛SQL可能看起來像這樣(有各種毛病此查詢,我知道,但我希望你的想法):

SELECT 
    T0.experiment_id as `id`, 
    (SELECT SUM(x.value) from 
     (SELECT value 
     FROM  data 
     WHERE experiment_id = t0.experiment_id 
     ORDER BY value 
     LIMIT t0.clip_index) as x) AS `sum` 
FROM data_clip AS t0 

幾個問題:

  1. LIMIT必須與定義常量(1000,10等),而不是列。
  2. 子查詢中的WHERE條件無法識別t0表,該表位於子查詢的外部。

我的問題基本上是如何完成主要使用SQL的兩個表之間的變量限制和總和。我想過使用group_concatsubstring_index來隔離每行的值高達clip_index,但是之後出現了總結編號字符串("1.2,2.3,3.2")和服務器限制緩衝區大小爲group_concat的問題(可配置,但值可以是~100k每個實驗)。有什麼想法嗎?謝謝。

回答

1

我猜你只需要包括與所選的每個值的行數和限制由行 像這樣數量的結果: (未未測試)

SELECT T0.experiment_id as `id`, 
(SELECT SUM(x.value) from  
(SELECT value,@rownum := @rownum + 1 AS rownum   
    FROM data   
    JOIN (SELECT @rownum := 0) r 
    WHERE experiment_id = t0.experiment_id   
    ORDER BY value    
) AS x 
WHERE x,rownum < t0.clip_index 
) AS `sum` 
FROM data_clip AS t0 

見:MySQL - Get row number on select

+0

非常酷!我現在唯一的問題仍然是讓子查詢知道'WHERE'子句中的't0.experiment_id'。想法? – sa125

+1

這裏有一篇很好的文章:http://explainextended.com/2009/03/05/row-sampling/ –

0

我認爲這將工作時,所有的價值觀是積極的。如果有負值,則需要更多等級。

SELECT experiment_id 
    , MIN(sumValue) - (MIN(cnt)-clip_id) * MIN(maxValue) 
     AS sumValue 
FROM 
    (SELECT e.experiment_id 
     , e.clip_id 
     , COUNT(*)   AS cnt 
     , SUM(d2.value) AS sumValue 
     , d.value   AS maxValue 
    FROM experiment AS e 
     JOIN data AS d 
     ON d.experiment_id = e.experiment_id 
     JOIN data AS d2 
     ON d2.experiment_id = e.experiment_id 
     AND d2.value <= d.value 
    GROUP BY e.experiment_id 
      , d.id        --- table's `data` Primary Key 
    HAVING COUNT(*) >= e.clip_id 
) AS grp 
GROUP BY experiment_id