2012-06-21 169 views
2

可能重複:
Delete duplicate rowsSQL刪除重複行

這裏是我的表結構:

「作者」(VARCHAR)| 「點」(整數)| 「Body」(文字)

作者永遠是一樣的,身體也是。相同的作者條目會在整個數據庫中出現多個不同的主體,所以我不能根據作者進行刪除。但是,點列並不總是相同的。我想要保持具有最大點值的行。

我正在使用SQLite3和Python。

感謝

編輯:

我已經試過這一點,但它只是刪除所有行。

for row in cur.fetchall(): 
     rows = cur.execute('SELECT * FROM Posts WHERE Author=? AND Body=? AND Nested=? AND Found=?', (row['Author'], row['Body'], row['Nested'], row['Found'],)) 
     for row2 in rows: 
      delrow = row 
      if (row['Upvotes'] < row2['Upvotes'] or row['Downvotes'] < row2['Downvotes']): 
       delrow = row2 
      cur.execute("DELETE FROM Posts WHERE Author=? AND Body=? AND Upvotes=? AND Downvotes=? AND Nested=? AND Found=?", (delrow['Author'], delrow['Body'], delrow['Upvotes'], delrow['Downvotes'], delrow['Nested'], delrow['Found'],)) 
      dn += 1 
      print "Deleted row ", dn 

我也試過這個,但它沒有工作。

cur.execute("DELETE FROM Posts WHERE Upvotes NOT IN (SELECT MAX(Upvotes) FROM Posts GROUP BY Body);") 

我也提交所有更改,所以它不是這樣。 SQLite3模塊安裝正確,我可以在數據庫上編寫。

+1

*蜂鳴聲*歡迎回到堆棧溢出,友好的用戶。請確保所有問題的措辭都是問題形式。此外,請保持禮貌並記得接受你的問題的答案。祝您有美好的一天。 *嗶聲* –

+0

你有什麼嘗試?重複行刪除通常使用某種排序功能完成,如ROWNUMBER,按作者和正文進行分區。 – Bort

+0

嘗試這樣做:http://stackoverflow.com/questions/6165895/delete-duplicate-rows,尤其是Vivek的答案。 (當然,您想切換不等式的方向以獲得最大的點值。) –

回答

2

不幸的是,在SQLite3中,你沒有像partition over row那樣好的功能,所以在一個查詢中沒有辦法做到這一點,所以你必須以程序方式或迭代方式進行。

出於性能方面的原因,我建議您提取刪除潛力的完整列表,然後將其全部刪除,例如。

# in your sql query 
SELECT ROWID, AUTHOR, BODY 
FROM TABLE_NAME 
ORDER BY AUTHOR, BODY, POINTS DESC 

然後在你的Python應用程序,遍歷結果集,並存儲爲作者/內容組合所有的非第一的ROWID(認爲CTRL-BREAK風格的編程),一旦你完成構建集刪除行ID。

+1

對於這種類型的刪除,您不需要「對分區進行分區」操作,因爲有一列可變(「分」 )。如果這些行完全相同,那麼你只需要這些,而不是。我很難相信提取數據,使用Python處理數據,然後將結果推回到數據庫,而不是在數據庫中執行它會更有效。 –

0

我沒有測試過,但是,這個可能工作:

DELETE FROM TableName 
    WHERE author, body, points NOT IN (SELECT author, body, MAX(points) as points 
     FROM TableName 
    GROUP BY author, body) 

運行它作爲一個SELECT查詢首先看它是否會keepwhat你想要的。

+0

除非點列是唯一的,否則這將不起作用。 你可以做的是從內部select中返回'author,body,max(points)',並在where子句中有''(作者,主體,點)不在[inner select]中'可以工作。 –

+0

謝謝,我根據您的建議更新了示例。我也加'body'到'group by'語句b/c我認爲這是必要的。 – plntxt

+0

啊,是的,你會在'group by'中需要它,否則它會失敗。錯過了那一個。 –

1

既然要刪除所有,但最高點值,下面會做就好了:

delete from test 
    where exists (select * from test t2 
       where test.author = t2.author 
       and test.body = t2.body 
       and test.points < t2.points); 

這是一個基本的加入到自身,然後刪除了具有相同作者的所有值&身體,但有一個較低的價值。

SqlFiddle這裏:http://sqlfiddle.com/#!7/64d62/3

注:一個需要注意的是,如果多個作者/體對具有相同的最大點值,那麼所有這些值將被保留。