2015-05-27 2 views
3

У меня есть таблица, которая выглядит примерно так:Вычислить процентное увеличение/уменьшение значения из предыдущего ряда

|date_start | date_end |amount | 
+------------+-------------+-------+ 
|2015-02-23 | 2015-03-01 |50  | 
|2015-03-02 | 2015-03-08 |50  | 
|2015-03-09 | 2015-03-15 |100 | 
|2015-03-16 | 2015-03-22 |800 | 
|2015-03-23 | 2015-03-29 |50  | 

, и я хотел бы работать процентное увеличение/уменьшение на колонке amount, от предыдущей даты , Например, результат будет примерно таким:

|date_start | date_end |amount | perc_change | 
+------------+-------------+-------+-------------+ 
|2015-02-23 | 2015-03-01 |50  | 
|2015-03-02 | 2015-03-08 |50  | 0 
|2015-03-09 | 2015-03-15 |100 | 50 
|2015-03-16 | 2015-03-22 |800 | 700 
|2015-03-23 | 2015-03-29 |50  | -750 

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

+0

вы можете создать [sql fiddle] (http://sqlfiddle.com), я сделал что-то подобное в sql-сервере, я думаю, что могу настроить его на это ... –

+0

Вы уверены, что вы рассчитываете процентное изменение? От 50 до 100 - это 100% -ное изменение, от 100 до 800 - изменение на 800% ... – Arth

+0

вот таблица скриптов sql, http://sqlfiddle.com/#!9/2c1ec6 – user3768071

ответ

3

Попробуйте это:

SELECT t.*, 
amount - (SELECT amount FROM transactions prev WHERE prev.date_end  < t.date_start ORDER BY date_start DESC LIMIT 1) AS changes 
FROM transactions t 
0

Это выглядит примерно так, я не имею среду, чтобы проверить это выбор, но я думаю, что он должен работать

SELECT t1.date_start, t1.date_end, t1.amount, (t1.amount - t2.amount) as perc_change 
    FROM table1 t1 
     JOIN table1 t2 ON t1.id = t2.id + 1 // here your join to 
    //get next row and calculate this perc_change field 
+0

получил это сообщение об ошибке ... Столбец 'date_start' в списке полей неоднозначен – user3768071

3

Если мы предположим, что предыдущая строка всегда заканчивается ровно за один день до начала тока (как в ваши данные образца), то вы можете использовать join. Процент увеличения будет:

select t.*, 
     100 * (t.amount - tprev.amount)/tprev.amount 
from atable t left join 
    atable tprev 
    on tprev.date_end = t.date_start - interval 1 day; 

Однако, ваши результаты, кажется, просто есть разница, которая легче вычислить:

select t.*, 
     (t.amount - tprev.amount) as diff 
from atable t left join 
    atable tprev 
    on tprev.date_end = t.date_start - interval 1 day; 
+1

Хороший улов, замечающий, что даты были на один день друг от друга! Если это согласовано, запрос становится намного проще. – AdamMc331

0

Я начал путем присоединения каждой строки в таблице с той, приходит после него, как это:

SELECT m.date_start AS mStart, mt.date_start AS mtStart 
FROM myTable m 
JOIN myTable mT ON m.date_start < mt.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start); 

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

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

SELECT 
    mT.date_start AS secondDate, 
    mT.amount - m.amount AS percentChange 
FROM myTable m 
JOIN myTable mT ON m.date_start < mT.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start); 

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

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

SELECT m.date_start, m.date_end, m.amount, tmp.percentChange 
FROM myTable m 
LEFT JOIN(
    SELECT 
    mT.date_start AS secondDate, 
    mT.amount - m.amount AS percentChange 
    FROM myTable m 
    JOIN myTable mT ON m.date_start < mT.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start) 
) tmp ON tmp.secondDate = m.date_start; 

А вот SQL Fiddle пример.

+0

McAdam, работает на SQL Fiddle, но при выполнении через MySQL, почему я получаю сообщение об ошибке ... Неизвестный столбец «mt.date_start» в разделе «on»? – user3768071

+0

@ user3768071 Возможно, вы сделали опечатку на одном из псевдонимов таблицы. Проверьте внимательно. – AdamMc331

+0

вот что я сначала подумал, поэтому я скопировал вашу точную таблицу и запрос без внесения каких-либо изменений, и я получаю сообщение об ошибке – user3768071

0

Вы случай использовать систему MySQL Var:

SELECT date_start, date_end, IF(@last IS NOT NULL,ammount - @last , '') as perc_change, @last := amount as amount 
From table 
ORDER BY date_start; 

вар @last устанавливается при каждом проходе, поэтому колонки порядок между perc_change и количеством важно

+0

Это не гарантирует правильные результаты: порядок оценки выражений с использованием пользовательских переменных не определен [см. Здесь] (https://dev.mysql.com/doc/refman/5.0/en/user-variables.html) –

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