Использовать значение столбца таблицы для LIMIT при выполнении соединения - PullRequest
1 голос
/ 16 августа 2011

У меня есть ситуация, когда я выполняю соединение между двумя таблицами, и мне нужно, чтобы значение из одной таблицы использовалось как фактор 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 

Как правило, я бы сделал этот расчет с некоторыми сценариями на стороне клиента (ruby, python и т. Д.), Но я хотел попробовать сделать это науровень дб.Некоторые воображаемые 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_concat и substring_index для изоляции значений до clip_index для каждой строки, но затем возникла проблема суммирования пронумерованных строк ("1.2,2.3,3.2") и ограничения сервера на размер group_concat буфер (настраивается, но значения могут быть около ~ 100k за эксперимент).Какие-нибудь мысли?Спасибо.

Ответы [ 2 ]

1 голос
/ 16 августа 2011

Полагаю, вам просто нужно включить номер строки с каждым выбранным значением и ограничить результаты количеством строк что-то вроде этого: (не проверено)

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 - Получить номер строки при выборе

0 голосов
/ 16 августа 2011

Я думаю, это будет работать, когда все значения положительные.Если есть отрицательные значения, необходим еще один уровень.

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
...