2016-03-14 59 views
7

我在我的SQLite數據庫中有6個表,每個表有6列(Date, user, NormalA, specialA, contact, remarks)和1000+行。python sqlalchemy不同列值

如何使用sqlalchemy對日期列進行排序以查找重複的日期並刪除該行?

+2

Q1:你還有一個單獨的主鍵列嗎? Q2:爲什麼你對這個問題有重要的** 6表格? – van

回答

1

Find duplicate values in SQL table的啓發,這可能幫助您選擇重複日期:

query = session.query(
    MyTable 
).\ 
    having(func.count(MyTable.date) > 1).\ 
    group_by(MyTable.date).all() 

如果你只想顯示獨特的日期; distinct on是你可能需要的東西

+0

不能做一個'func.count'。似乎沒有那個選擇 –

+1

@jakewong你導入函數:'from sqlalchemy import func'? – Parfait

1

雖然我喜歡SQLAlchemy的整個面向對象方法,但有時我發現直接使用某些SQL更容易。 由於記錄沒有密鑰,我們需要行號(_ROWID_)來刪除目標記錄,我不認爲API提供了它。

所以首先我們連接到數據庫:

from sqlalchemy import create_engine 
db = create_engine(r'sqlite:///C:\temp\example.db') 
eng = db.engine 

然後列出所有的記錄:

for row in eng.execute("SELECT * FROM TableA;") : 
    print row 

並顯示所有重複的記錄中,其中日期是相同的:

for row in eng.execute(""" 
    SELECT * FROM {table} 
    WHERE {field} IN (SELECT {field} FROM {table} GROUP BY {field} HAVING COUNT(*) > 1) 
    ORDER BY {field}; 
    """.format(table="TableA", field="Date")) : 
    print row 

現在我們確定了所有重複項,如果其他項重複項可能需要修復場是不同的:

eng.execute("UPDATE TableA SET NormalA=18, specialA=20 WHERE Date = '2016-18-12' ;"); 
eng.execute("UPDATE TableA SET NormalA=4, specialA=8 WHERE Date = '2015-18-12' ;"); 

而且finnally保持第一插入的記錄並刪除最近的重複記錄:

print eng.execute(""" 
    DELETE FROM {table} 
    WHERE _ROWID_ NOT IN (SELECT MIN(_ROWID_) FROM {table} GROUP BY {field}); 
    """.format(table="TableA", field="Date")).rowcount 

或者保持最後插入的記錄並刪除其他重複的記錄:

print eng.execute(""" 
    DELETE FROM {table} 
    WHERE _ROWID_ NOT IN (SELECT MAX(_ROWID_) FROM {table} GROUP BY {field}); 
    """.format(table="TableA", field="Date")).rowcount 
2

假設這是你的模型:

class MyTable(Base): 
    __tablename__ = 'my_table' 
    id = Column(Integer, primary_key=True) 
    date = Column(DateTime) 
    user = Column(String) 
    # do not really care of columns other than `id` and `date` 
    # important here is the fact that `id` is a PK 

以下兩種方法來刪除你的數據:

  1. 查找重複,將它們標記爲刪除並提交事務
  2. 創建一個SQL查詢,這將直接對數據庫執行刪除操作。

對他們倆的幫手子查詢將用於:

# helper subquery: find first row (by primary key) for each unique date 
subq = (
    session.query(MyTable.date, func.min(MyTable.id).label("min_id")) 
    .group_by(MyTable.date) 
) .subquery('date_min_id') 

選項1:查找重複,將它們標記爲刪除並提交事務

# query to find all duplicates 
q_duplicates = (
    session 
    .query(MyTable) 
    .join(subq, and_(
     MyTable.date == subq.c.date, 
     MyTable.id != subq.c.min_id) 
    ) 
) 

for x in q_duplicates: 
    print("Will delete %s" % x) 
    session.delete(x) 
session.commit() 

選項-2:創建一個直接在數據庫上執行刪除的SQL查詢

sq = (
    session 
    .query(MyTable.id) 
    .join(subq, and_(
     MyTable.date == subq.c.date, 
     MyTable.id != subq.c.min_id) 
    ) 
).subquery("subq") 

dq = (
    session 
    .query(MyTable) 
    .filter(MyTable.id.in_(sq)) 
).delete(synchronize_session=False)