2014-09-05 168 views
0

我有如下表计算差异

+-----+--------+-----------+-----------+-------+ 
| id | job_id | source_id | target_id | value | 
+-----+--------+-----------+-----------+-------+ 
| 204 | 5283 |  247 |  228 | 1201 | 
| 349 | 4006 |  247 |  228 | 100 | 
| 350 | 4007 |  247 |  228 | 500 | 
| 351 | 4008 |  247 |  228 | 1000 | 
| 352 | 4009 |   1 |  100 | 100 | 
| 353 | 4010 |   1 |  100 | 500 | 
| 354 | 4011 |   1 |  100 | 50 | 
+-----+--------+-----------+-----------+-------+ 

我想列通过SOURCE_ID和target_id之间的电邮宣传创建一个差异。较旧的(较小的ID)应该与较新的一个进行比较

我已经搜索了一点点,发现​​3210。我已经写了一个小的查询,并在“一般”的作品,而不是作为expexted:

SELECT 
    c.id, c.source_id, c.target_id, c.value, COALESCE(c1.value - c.value, -1) AS diff 
FROM 
    changes c LEFT JOIN changes c1 ON (c1.source_id = c.source_id AND c1.target_id = c.target_id) 
GROUP BY c.source_id, c.target_id, c.job_id 
ORDER BY c.id 

我得到了以下结果:

+-----+-----------+-----------+-------+------+ 
| id | source_id | target_id | value | diff | 
+-----+-----------+-----------+-------+------+ 
| 204 |  247 |  228 | 1201 | 0 | 
| 349 |  247 |  228 | 100 | 1101 | 
| 350 |  247 |  228 | 500 | 701 | 
| 351 |  247 |  228 | 1000 | 201 | 
| 352 |   1 |  100 | 100 | 0 | 
| 353 |   1 |  100 | 500 | -400 | 
| 354 |   1 |  100 | 50 | 50 | 
+-----+-----------+-----------+-------+------+ 

你可以看到DIFF工作编号349和353,我希望对所有行都有如下预期结果:

+-----+-----------+-----------+-------+------+ 
| id | source_id | target_id | value | diff | 
+-----+-----------+-----------+-------+------+ 
| 204 |  247 |  228 | 1201 | 1201 | 
| 349 |  247 |  228 | 100 | 1101 | 
| 350 |  247 |  228 | 500 | -400 | 
| 351 |  247 |  228 | 1000 | -500 | 
| 352 |   1 |  100 | 100 | 100 | 
| 353 |   1 |  100 | 500 | -400 | 
| 354 |   1 |  100 | 50 | 450 | 
+-----+-----------+-----------+-------+------+ 

如果差异结果是反转的,那就没有问题了。

我错过了什么?
感谢您的任何提示。

+1

什么是您预期的输出? – 2014-09-05 12:58:46

+1

Plz明确你想要达到的目标。 – 2014-09-05 13:03:24

+0

对不起,我忘了补充一点。我认为差异很明显。我已经添加了样本预期的输出 – CSchulz 2014-09-05 13:19:51

回答

3

如果使用用户定义的变量,你不需要参加表本身。只是做逐行comparrision像这样

SELECT 
    id, 
    job_id, 
    target_id, 
    if(@a = source_id, @b - value, value) as diff, 
    @b := value as value, 
    @a := source_id as source_id 
FROM changes 
CROSS JOIN (SELECT @a:=0, @b:=0)t 

DEMO

+1

+1简洁的郁郁葱葱,我知道你喜欢你的@vars。 – Arth 2014-09-05 14:12:45

+1

@Arth大声笑我的连接方法将只是你的副本..所以我必须有一些'独创性':P – 2014-09-05 14:13:52

2

我想你想:

SELECT c.id, 
      c.source_id, 
      c.target_id, 
      c.value, 
      c.value - COALESCE(co.value, 0) delta 
    FROM changes c 
LEFT JOIN (
     SELECT ci.id, MAX(cio.id) prev_id 
     FROM changes ci 
     JOIN changes cio 
      ON cio.source_id = ci.source_id 
      AND cio.target_id = ci.target_id 
      AND cio.id < ci.id 
    GROUP BY ci.id 
     ) link 
     ON link.id = c.id 
LEFT JOIN changes co 
     ON co.id = link.prev_id 
ORDER BY c.id 

我稍微改变了逻辑。

在您预期的结果,第一DIFF已经从未知(0?)去了1201和报告为阳性差异,但第二次从1201去了100,并且还在报告为阳性。

我已经改名为增量,并给予您从先前的值移到新值所需的数量。

COALESCE(co.value-c.value, c.value) diff 

这将得到您所提供的结果(改为-500,这点我相信DIFF 500是一个错字):很显然,如果你愿意,你可以改变这一点。

+1

我dono关于亚勒,但我要去扔一些+ 1的:) – 2014-09-05 14:09:59

+0

@JohnRuddell干杯。 Targik仍在等待他...... :) – Arth 2014-09-05 14:14:19

+1

Targik没有给出答案......应该是一个评论。如果它提供了一个解决方案,我肯定会给+1 ..多数民众赞成在这里是什么:) – 2014-09-05 14:15:06

3

我怀疑你正在寻找这样的事情 - 虽然COALESCE位似乎误导我...

SELECT a.*, COALESCE(b.value-a.value,a.value) diff 
    FROM 
    (SELECT x.* , COUNT(*) rank FROM changes x JOIN changes y ON y.id <= x.id GROUP BY x.id) a 
    LEFT 
    JOIN 
    (SELECT x.* , COUNT(*) rank FROM changes x JOIN changes y ON y.id <= x.id GROUP BY x.id) b 
    ON b.source_id = a.source_id 
    AND b.rank = a.rank - 1; 
+0

喜欢它,采用不同的方法,不知道哪个更快!我偷了你的COALESCE btw作为我的附录,因为它更可读。 – Arth 2014-09-05 14:00:02

+0

嗯,我认为我的结果是正确的 - 所以它可能不会赢得表现,但是......! ;-) – Strawberry 2014-09-05 14:03:16

+0

请解释我的不怎么给出正确的结果(附录) – Arth 2014-09-05 14:04:12