Python3 SQLAlchemy 删除重复项

squ*_*idg 6 python sqlalchemy

我正在使用 SQLAlchemy 来管理数据库,并尝试删除所有包含重复项的行。该表有一个 id(主键)和域名。

示例:
ID| 域
1 | example-1.com
2 | example-2.com
3 | example-1.com

在本例中,我想删除 example-1.com 的 1 个实例。有时我需要删除超过 1 个域,但一般来说,数据库不应多次拥有一个域,如果有,则只应保留第一行,而应删除其他行。

sna*_*erb 4

假设你的模型看起来像这样:

import sqlalchemy as sa
from sqlalchemy import orm

Base = orm.declarative_base()


class Domain(Base):
    __tablename__ = 'domain_names'

    id = sa.Column(sa.Integer, primary_key=True)
    domain = sa.Column(sa.String)
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样删除重复项:

# Create a query that identifies the row for each domain with the lowest id
inner_q = session.query(sa.func.min(Domain.id)).group_by(Domain.domain)
aliased = sa.alias(inner_q)
# Select the rows that do not match the subquery
q = session.query(Domain).filter(~Domain.id.in_(aliased))

# Delete the unmatched rows (SQLAlchemy generates a single DELETE statement from this loop)
for domain in q:
    session.delete(domain)
session.commit()

# Show remaining rows
for domain in session.query(Domain):
    print(domain)
print()
Run Code Online (Sandbox Code Playgroud)

如果您不使用 ORM,则核心等效项是:

meta = sa.MetaData()
domains = sa.Table('domain_names', meta, autoload=True, autoload_with=engine)

inner_q = sa.select([sa.func.min(domains.c.id)]).group_by(domains.c.domain)
aliased = sa.alias(inner_q)

with engine.connect() as conn:
    conn.execute(domains.delete().where(~domains.c.id.in_(aliased)))
Run Code Online (Sandbox Code Playgroud)

这个答案是基于这个答案中提供的SQL 。还有其他删除重复项的方法,您可以在链接上的其他答案中看到这些方法,或者通过谷歌搜索“sql删除重复项”或类似的方法。