2013-06-20 33 views
3

我有一個表,其中包含,除了其他,這樣的領域:id integer, status_id integer, add_date date如何只更新匹配值的一定百分比

我想執行類似這樣的查詢:

update table set status_id = new_status_id where status_id = old_status_id

而是一個只會更新值的給定的百分比,比如50%。而且,每個日期的更新行的分佈應該是相似的;我想更新date = 23.06.2013半行,而不是一半。

回答

6
update table 
set status_id = new_status_id 
where 
    status_id = old_status_id 
    and random() < 0.5 
+0

簡單的,但不會考慮日期。它可以更新整個表(如果它足夠小) –

+0

@IgorRomanchenko關於日期的不精確更新是可以接受的,並且這個查詢是最簡單的可能。因此接受。謝謝你的工作,謝謝。 – Dariusz

2

該查詢會給你行的id,要更新:

SELECT * 
FROM 
(SELECT id, 
     count(id) OVER (PARTITION BY add_date) cnt, 
     row_num() OVER (PARTITION BY add_date ORDER BY id) rn 
FROM table 
WHERE status_id = old_status_id) sub 
WHERE rn <= cnt * 0.5 -- your percentage 
-- WHERE rn <= cnt * 0.5 + random() -- another (better) version. 
            -- Will update at random if there if only one row 
+1

'ORDER BY id' ..它不在請求中首先更新較小的ID。你可以刪除子句以獲得任意選擇(這會更快,因爲兩個窗口函數共享相同的窗口),或者用'ORDER BY random()'替換它以獲得真正的隨機選擇。 –

+0

@ErwinBrandstetter是的,我知道。這只是一種習慣,將ORDER BY添加到具有任意列的row_num()中(否則Oracle會拋出錯誤)。在不需要時使用'random()'不是很好。 (調用'random()'可能不便宜) –

+0

_if它足夠小,因爲你對我的答案的評論,那麼這也不是完美的,因爲沒有一個只有一行的日期將被刪除。還有一個小錯誤,即count和row_number都返回整數。解決辦法就像'rn :: float/cnt' –

0

當躺在牀上,並試圖睡一個非常簡單的解決方案來到我的腦海:

update table 
set status_id = new_status_id 
where 
     status_id = old_status_id 
    and id % 2 = 0; 

由於id實際上是bigserial,所以此查詢將與Clodoaldo具有相似的效果。