2015-04-21 4 views
1

Как рассчитать разницу между каждой строкой и возвращают общую сумму, а также, как писать его в порядке. (Я использую MySQL)Подсчитайте сумму разницы между строками в MySQL

(Там будет пробелы в столбце ID)

id --- session --- value 
1.........3..........15 
4.........3...........5 
7.........3...........8 
10........3..........13 
11........3...........9 

от id.1 до id.4 разница составляет
от id.2 до id.3 разница составляет
От id.3 разности id.4 является
От id.4 до id.5 разница составляет
Общая сумма =

Это то, что я пришел (и да его полностью неправильно)

SET @oldV = 0; 

SELECT SUM(table.x) 
FROM(
    SELECT @oldV := value AND IF(value > @oldV, @x:=(value - @oldV), @x:=(@oldV - value)) x 
    FROM TheTable WHERE session = 3 ORDER BY id) table; 
+0

Покажите нам ваши усилия. Вы что-то пробовали? или это просто домашнее задание? – Manwal

+0

Вы не можете сделать это с помощью одного запроса. Для этого вам нужно использовать некоторые программные средства. – Manwal

+0

Являются ли 'id' непрерывной последовательностью? – Fox

ответ

1

Там много способов получить указанное результат.

Одной из возможностей (специфичной для MySQL) является использование определяемой пользователем переменной для хранения значения из предыдущей строки, поэтому вы можете сравнить ее с «значением» из текущей строки.

Примечание: поведение пользовательских переменных MySQL, указанных в инструкции, как указано ниже, не определено. Справочное руководство по MySQL предостерегает в зависимости от поведения пользовательских переменных в контексте, подобном этому. НО ... мы наблюдаем повторяющееся последовательное поведение в MySQL 5.1 и 5.5.

SELECT SUM(d.diff) AS tot_diff 
    FROM (SELECT ABS(t.`value`[email protected]) AS diff 
       , @pvalue := t.`value` 
      FROM mytable t 
      CROSS 
      JOIN (SELECT @pvalue := NULL) i 
      ORDER BY t.id 
     ) d 

Обратите внимание, что это важно, что определяемая пользователем переменная инициализируется, так как переменная сохраняется в течение сессии, не только заявление. Вот почему мы включаем инициализацию во встроенном виде (производная таблица i). При желании мы могли бы запустить отдельный оператор SET @pvalue := NULL;, прежде чем запускать запрос.

+0

Мне нравится ваша идея, но я получаю сообщение об ошибке «... правильный синтаксис для использования рядом с« END ». Я создаю код в процедуре, и я не думаю, что с этой процедурой что-то не так. Есть идеи что это может быть? – user3800924

+0

@ user3800924: в хранимой программе MySQL операторы должны заканчиваться точкой с запятой. Если вы включите в процедуру инструкцию SELECT (например, выше), результат будет возвращен клиенту. Если вы не хотите возвращать набор результатов, вам нужно будет сделать что-то еще с возвращаемой строкой, например, «SELECT ... INTO», «INSERT INTO ... SELECT», объявить/открыть/выборка из курсора и т. д., – spencer7593

+0

@ user3800924: Похоже, я пропустил предикат, который вы указали в своем исходном запросе ... 'session = 3'. Если вам это нужно, измените запрос выше, добавив ** 'WHERE t.session = 3' ** перед предложением' ORDER BY'. – spencer7593

3

Основываясь на вашем примере, вы, кажется, вычисляете абсолютную разницу между строками. Вы можете сделать это с помощью инструкции объединения. Попробуйте что-нибудь вроде:

select a.id,b.id,abs(a.value - b.value) as dif 
from UserData as a 
inner join 
UserData as b 
on a.id = b.id - 1 

после того, как у вас есть diff col, вы можете сделать сумму. Если будут пробелы в ид создать новый Col ROWNUMBER, который не имеет разрывов, а затем использовать что вместо идентификатора как ваш заявление

1

Мне это не очень нравится, но, похоже, он работает.

SELECT 
    SUM(
     ABS(t1.num - t2.num) 
    ) AS sumofdiffs 
    FROM sumdiff AS t1 
    JOIN sumdiff AS t2 
     ON(
      (SELECT MIN(id) FROM sumdiff AS t3 WHERE t3.id > t1.id) = t2.id 
    ) 
; 

Найден другой способ. Используя только подзапрос, нет соединений. Это все еще довольно медленно. Но лучше всего использовать первый запрос.

SELECT 
    SUM( 
     ABS(t1.num - 
      (SELECT num FROM sumdiff WHERE id > t1.id ORDER BY id ASC LIMIT 1) 
     ) 
    ) AS summofdiffs 
FROM sumdiff AS t1; 

SQLFiddle

+0

Это хорошо работает, спасибо за ответ :) – user3800924

+0

@ пользователь3800924 без проблем. просто имейте в виду, что это очень медленно (пробовал мой на 2mio рядах ... 9 часов и все еще работает), а другие решения, вероятно, будут быстрее. (хотя, возможно, это что-то где-то) – Fox

+0

40 часов и все еще работает: D Не очень эффективен. – Fox

Смежные вопросы