我有下表
+-----+--------+-----------+-----------+-------+
| 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)应与较新的
进行比较我搜索了一下,发现coalesce
。我写了一个小查询,它在" general"中工作,但没有被驱逐:
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 |
+-----+-----------+-----------+-------+------+
你可以看到id为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 |
+-----+-----------+-----------+-------+------+
如果反转差异结果将没有问题。
我错过了什么?
感谢任何提示。
答案 0 :(得分: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;
答案 1 :(得分:3)
如果您使用用户定义的变量,则不需要将表连接到自身。只是按行进行比较
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
答案 2 :(得分: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
我稍微改变了逻辑。
在您的预期结果中,第一个差异从未知(0?)变为1201并报告为正差异,但第二个差异从1201变为100,仍然报告为正。
我已将名称更改为delta,并为您提供从上一个值移至新值所需的数字。显然,如果你想要改变这个:
COALESCE(co.value-c.value, c.value) diff
它将为您提供您提供的结果(将差异500更改为-500,我相信这是一个错字)。