2012-06-21 135 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

注:一个需要注意的是,如果多个作者/体对具有相同的最大点值,那么所有这些值将被保留。