2011-06-06 82 views
3

不知道如何描述我試圖從這個問題得到什麼,但這裏去...根據原始行從另一個表的平均更新行

我有一張客戶購買表' t1',包含關於購買的信息:客戶ID,日期,如果客戶是獨自一人,則爲布爾值,以及購買金額。在第二個表中t2是具有日期和布爾型的相同客戶ID的另一個列表,表明他們是否是單獨的。

我想更新第二個表格,其中包含他們之前做過的x次購買的值的平均值,以及它們是否是單獨的。

我的設置與表:

DROP TABLE IF EXISTS t1; 
DROP TABLE IF EXISTS t2; 
CREATE TABLE t1 (cid INT, d DATE, i INT, v FLOAT); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-01', 0, 10); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-02', 1, 20); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-03', 1, 30); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-04', 1, 40); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-05', 0, 50); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-06', 0, 60); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-07', 0, 70); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-08', 1, 80); 
INSERT INTO t1 (cid, d,i,v) VALUES (1,'2001-01-09', 0, 90); 
INSERT INTO t1 (cid, d,i,v) VALUES (2,'2001-01-04', 1, 35); 
CREATE TABLE t2 (cid INT, d DATE, i INT, av2 FLOAT, av3 FLOAT); 
INSERT INTO t2 (cid, d,i) VALUES (1,'2001-01-07', 0); 
INSERT INTO t2 (cid, d,i) VALUES (1,'2001-01-08', 1); 
INSERT INTO t2 (cid, d,i) VALUES (2,'2001-01-08', 0); 
INSERT INTO t2 (cid, d,i) VALUES (2,'2001-01-09', 1); 

av2av3在哪裏,我想最後23交易的平均列。所以我需要一個更新聲明(真的有兩個聲明,一個用於av2,另一個用於av3)來說:「當這個客戶進入這個日期,並且他們獨自進來或沒有進貨時,他們最後一次x購買的平均值是多少。」

因此所產生的數據應該是:

CID二AV2 AV3


1 2001年1月7日0 55 40
1 2001年1月8日1 35 40
2 2001- 01-08 0 null null
2 2001-01-08 1 35 35

我得到的最接近是這樣的:

UPDATE t2 SET av=(
SELECT AVG(tcol) 
FROM (
SELECT v AS tcol FROM t1 LIMIT 2 
) AS tt); 

這似乎在朝着正確的方向(限2是想通過AV列23。但是,這只是平均x先前購買(不管客戶或布爾值)。只要我在WHERE子句中鏈接數據,它就會扼殺:

UPDATE t2 SET av=(
SELECT AVG(tcol) 
FROM (
SELECT v AS tcol FROM t1 WHERE t1.d<t2.d and t1.i=t2.i LIMIT 2 
) AS tt); 

任何想法?有什麼我想要做的名字嗎?我需要以不同的方式來描述嗎?有什麼建議麼?

謝謝, 菲利普

+0

它被稱爲「移動平均值」或「滾動平均值」。兩個很好的解決方案在這裏: [http://stackoverflow.com/questions/878473/how-do-i-calculate-a-moving-average-using-mysql](http://stackoverflow.com/questions/878473/我怎麼做,我計算移動平均使用MySQL) – jaeheung 2013-08-17 01:53:13

回答

1

嘗試這一個 -

SET @r = 0; 
SET @cid = NULL; 
SET @i = NULL; 

UPDATE t2 JOIN (
    SELECT t.cid, t.d, t.i, AVG(IF(t.r < 3, t.v, NULL)) av2, AVG(IF(t.r < 4, t.v, NULL)) av3 FROM (
    SELECT t.*, IF(@cid = t.cid AND @i = t.i, @r := @r + 1, @r := 1) AS r, @cid := t.cid, @i := t.i FROM (
     SELECT t2.*, t1.v FROM t2 
     JOIN t1 
      ON t1.cid = t2.cid AND t1.d < t2.d AND t1.i = t2.i 
     ORDER BY t2.cid, t2.i, t1.d DESC 
    ) t 
    ) t 
    GROUP BY t.cid, t.i, t.d 
) t 
    ON t2.cid = t.cid AND t2.i = t.i AND t2.d = t.d 
SET t2.av2 = t.av2, t2.av3 = t.av3; 

SELECT * FROM t2; 
+------+------------+------+------+------+ 
| cid | d   | i | av2 | av3 | 
+------+------------+------+------+------+ 
| 1 | 2001-01-07 | 0 | 55 | 40 | 
| 1 | 2001-01-08 | 1 | 35 | 30 | 
| 2 | 2001-01-08 | 0 | NULL | NULL | 
| 2 | 2001-01-09 | 1 | 35 | 35 | 
+------+------------+------+------+------+ 

注: 爲CID = 1,d = 2001年1月8日的值AV3,I = 1應爲30 ,究竟? ...不是40.

+0

哇,這是一個相當的聲明。你說的對,它應該是30,而不是40.我會試一試。有一個問題,如果我想添加另一個avg列,比如avg5,就足夠了,只需在第一個選擇像AVG(IF(t.r <6,t.v,NULL))av5'中放入另一個字段就足夠了? – user548084 2011-06-06 20:24:56

+0

是的,你可以這樣做,因爲't'.'r'是一個組中的行數。 – Devart 2011-06-07 10:08:09

+0

如果'i'是一個整數值而不是布爾值,它會有所作爲嗎?比較仍然是'=',但我改變了查詢upa它,它現在似乎在做所有值的平均值(不考慮't.r'約束)。試圖找出我導致問題的變化... – user548084 2011-06-07 23:31:18

相關問題