1. 从“查重”这个日常需求说起
不知道你有没有遇到过这种情况:从数据库里拉出一堆用户数据,准备做个分析,结果发现同一个人的记录出现了好几次。或者,你想看看网站都有哪些不同的访问来源,结果查询结果里同一个域名重复了N遍。这种时候,你心里肯定在想:“能不能把这些重复的玩意儿给去掉,让我看得清楚点?”
没错,这就是“数据去重”的典型场景。在数据库操作里,它是个高频又基础的需求。今天我们不聊那些复杂的ETL流程,就聚焦在SQLAlchemy这个Python里最流行的ORM(对象关系映射)工具上,看看怎么用它又快又好地搞定数据去重。
我刚开始用SQLAlchemy那会儿,也在这个问题上迷糊过。明明在SQL语句里写个DISTINCT关键字那么简单,怎么到了ORM里就感觉有点绕呢?特别是当你想对多列组合进行去重时,那个语法乍一看还真有点让人摸不着头脑。后来踩过几次坑,把官方文档翻来覆去看了几遍,又在项目里实际用了无数次之后,总算摸清了门道。今天我就把这些实战经验,用最直白的话分享给你,保证你看完就能上手,再也不用为去重发愁。
简单来说,SQLAlchemy的去重核心,就是distinct()这个方法和func.distinct()这个函数。它们俩分工合作,能帮你处理从单列到多列的各种去重需求。下面,我们就从最简单的单列去重开始,一步步深入到更复杂的场景。
2. 单列去重:一招搞定重复值
单列去重是最常见的情况。比如,你有一张users表,里面有个city字段,你想知道你的用户都分布在哪些不同的城市,而不关心每个城市有多少人。
2.1 基础玩法:使用distinct()函数
在SQLAlchemy的ORM查询中,最直接的单列去重方法是使用sqlalchemy.func模块里的distinct()函数。你可以把它理解为一个“包裹器”,把你要去重的列包起来,告诉数据库:“嘿,处理这一列的时候,重复的只算一个。”
我们来个实际的例子。假设我们有一个Article模型,代表文章,其中有一个category字段表示文章分类。
from sqlalchemy import create_engine, Column, String, Integer, func, distinct
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 1. 定义模型
Base = declarative_base()
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String)
category = Column(String) # 文章分类
author = Column(String)
# 2. 创建引擎和会话
engine = create_engine('sqlite:///example.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# 3. 查询所有不重复的文章分类
distinct_categories = session.query(func.distinct(Article.category)).all()
print(distinct_categories)
运行上面的代码,distinct_categories会是一个元组组成的列表,像[('科技',), ('生活',), ('体育',)]这样,每个元组里只有一个元素,就是那个唯一的分类名。
这里有个小细节要注意:query(func.distinct(Article.category))查询返回的是Article.category这一列的去重结果。.all()方法返回的是一个列表,里面的每个元素都是一个元组,哪怕你只查询了一列。所以你需要通过result[0]这样的方式来获取具体的值。


2498

被折叠的 条评论
为什么被折叠?



