我有一张看起来像这样的桌子:
|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
我已经搜索并绞尽脑汁好几天了。通常,我只是使用服务器端代码来执行此操作,但现在我需要将其全部包含在查询中。
试试这个:
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
如果我们假设前一行始终在当前行开始前一天结束(如示例数据中所示),那么您可以使用
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;
您可以使用
lag()
窗口功能来使其更容易:
select date_start,
date_end,
amount,
LAG(amount, 1, 0) OVER (ORDER BY date_start) as previous_amount,
amount - LAG(amount, 1, 0) OVER (ORDER BY date_start) as amount_diff,
((amount - LAG(amount, 1, 0) OVER (ORDER BY date_start)) / (amount - LAG(amount, 1, 0) OVER (ORDER BY date_start))) * 100 amount_diff_percentage
from your_table_name
我首先将表中的每一行与其后面的一行连接起来,如下所示:
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 查询以显示与之前日期相比的百分比变化,如下所示:
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 示例。
它看起来像这样,我没有环境来测试这个选择,但我认为它应该工作
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
您使用 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;
var @last 在每个段落中设置,因此 perc_change 和 amount 之间的列顺序很重要