2011-02-05 134 views
0

我正在根據基於其他行的特定條件更新某些行。比方說表是這樣的:mysql - 基於其他行的更新行

COLUMNS: time    type  genre doubles  triples 
ROW 1: 2010.06.21 12:00 1  1  0   0 
ROW 2: 2010.06.21 12:00 1  2  0   0 
ROW 3: 2010.06.21 12:00 1  1  0   0 
ROW 4: 2010.06.21 12:00 2  3  0   0 
ROW 5: 2010.06.22 12:00 2  2  0   0 
ROW 6: 2010.06.22 12:00 2  3  0   0 
ROW 7: 2010.06.22 12:00 1  1  0   0 

我期待更新基於以下規則doublestriples列:

1)僅看更新行,其中行之間的time=timetype=type (例如行1,2,3和行5 & 6)。

2)接着計數的那些行之間不同genre「S的#,如果有兩個不同的genresdoubles柱更改爲1,或者如果存在三個則triples柱更改爲1 SO例如在上面第1,2,3行的表格會有doubles=1,因爲三行之間有兩種不同的流派。第5行和第6行也將有doubles=1,因爲行之間還有兩種不同的流派。 Doubles can = 1和triples can = 1但不是兩者都可以。

現在,我可以很容易地寫出一些基於這些規則的PHP,我想,但我想知道是否有辦法在mysql中完成這一切?看起來我總是很驚訝你可以從SQL語句中完成的數量。

也許像(爲doublestriples列兩個不同的語句):

雙打 - UPDATE myTable SET (doubles=1) WHERE time=time AND type=type ...但後來你會如何解釋上述規則#2(具有獨特風格的行計數數)。

這是可能的在MySQL中或PHP只是正確的方式去這裏?

預先感謝

回答

1

當然,你可以在一個查詢中做到這一點。使用此示例表:

create table duotri (time varchar(100), type int, genre int, doubles int, triples int); 
insert duotri values 
('2010.06.21 12:00' ,1  ,1  ,0   ,0), 
('2010.06.21 12:00' ,1  ,2  ,0   ,0), 
('2010.06.21 12:00' ,1  ,1  ,0   ,0), 
('2010.06.21 12:00' ,2  ,3  ,0   ,0), 
('2010.06.22 12:00' ,2  ,2  ,0   ,0), 
('2010.06.22 12:00' ,2  ,3  ,0   ,0), 
('2010.06.22 12:00' ,1  ,1  ,0   ,0); 

update語句應該加入到分組的形式來獲得一倍和三倍。

update duotri t1 
inner join (
    select time, type, 
    case when count(distinct genre) = 2 then 1 else 0 end doubles, 
    case when count(distinct genre) = 3 then 1 else 0 end triples 
    from duotri 
    group by time, type) t2 
    on t1.time=t2.time and t1.type=t2.type 
set t1.doubles=t2.doubles, t1.triples = t2.triples; 
+0

謝謝我會玩這個有點讓你知道它是如何工作的 – themerlinproject 2011-02-06 04:23:06

1

它可以使用子選擇和CASE表達或由計數進行比較來計爲列是可能的,但是這將是困難的,因爲這樣的事實,MySQL不讓您選擇在子選擇中正在更新的表格。

您可以輕鬆地做一個選擇(我給表「錄音」的名稱,因爲你沒有指定它,給樣本中的SQL,而不是預格式化文本始終是有幫助的):

SELECT r0.id, r0.`time`, r0.`type`, r0.`genre`, 
    COUNT(DISTINCT r1.genre) = 2 AS doubles, 
    COUNT(DISTINCT r1.genre) = 3 AS triples 
    FROM recordings AS r0 
    JOIN recordings AS r1 ON r0.`time`=r1.`time` AND r0.`type`=r1.`type` 
    GROUP BY r0.`id`, r0.`time`, r0.`type`, r0.`genre` 

然後,您可以使用它作爲一個stored procedureview的基礎:

ALTER TABLE recordings DROP COLUMN doubles; 
ALTER TABLE recordings DROP COLUMN triples; 
ALTER TABLE recordings ADD id INT PRIMARY KEY AUTO_INCREMENT; 

CREATE VIEW recording_genre_count AS 
SELECT r0.id, r0.`time`, r0.`type`, r0.`genre`, 
    CASE COUNT(DISTINCT r1.genre) WHEN 2 THEN 1 ELSE 0 END AS doubles, 
    CASE COUNT(DISTINCT r1.genre) WHEN 3 THEN 1 ELSE 0 END AS triples 
    FROM recordings AS r0 
    JOIN recordings AS r1 ON r0.`time`=r1.`time` AND r0.`type`=r1.`type` 
    GROUP BY r0.`id`, r0.`time`, r0.`type`, r0.`genre`; 
    --Since the columns of recordings are functionally dependent on recordings.id, 
    --you could use just "GROUP BY r0.id", but the above will work on other 
    -- DBMSs 

如果組更換頻繁,認爲是一個更好的選擇。它也確保數據consistency。如果必須運行查詢來更新doublestriples列,那麼在插入行後DB會經常處於不一致狀態(triggers可以幫助解決這個問題,但是像UPDATE中的子選擇一樣,觸發器在從一張正在更新的表格)。視圖和查詢也更容易允許附加列(例如quadruples)而不是存儲過程。