2014-09-05 235 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