簡體   English   中英

python sqlalchemy不同的列值

[英]python sqlalchemy distinct column values

我的SQLite數據庫中有6個表,每個表有6列( Date, user, NormalA, specialA, contact, remarks )和1000多行。

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

假設這是你的模型:

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)

SQL表中查找重復值的啟發,這可能有助於您選擇重復日期:

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

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

雖然我喜歡使用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' ;");

並最終保留第一個插入的記錄並刪除最新的重復記錄:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM