如何在clickhouse-sqlalchemy中使用UNION DISTINCT
如何在clickhouse-sqlalchemy中使用UNION DISTINCT
我来帮你解决这个问题!其实有几种不同的方式可以实现,下面给你逐一说明:
方法一:使用SQLAlchemy原生的union()函数
SQLAlchemy核心库自带的union()方法默认就是生成去重的联合查询,对应ClickHouse的UNION DISTINCT。clickhouse-sqlalchemy会自动把这个表达式转换成符合ClickHouse语法的语句,完全不需要额外配置。
举个实际的代码例子:
from sqlalchemy import select, union, MetaData from clickhouse_sqlalchemy import create_engine, Table, Column, String, Integer # 初始化连接和表结构 engine = create_engine('clickhouse://localhost/default') metadata = MetaData(bind=engine) table1 = Table('table1', metadata, Column('id', Integer), Column('name', String)) table2 = Table('table2', metadata, Column('id', Integer), Column('name', String)) # 构造两个基础查询 query1 = select(table1.c.id, table1.c.name) query2 = select(table2.c.id, table2.c.name) # 用union()生成UNION DISTINCT查询 union_distinct_query = union(query1, query2) # 执行查询 with engine.connect() as conn: results = conn.execute(union_distinct_query).fetchall()
这个方法最符合SQLAlchemy的使用习惯,也能充分利用ORM的类型安全和灵活性。
方法二:直接用原生SQL语句拼接(备选方案)
如果你需要更直接地控制SQL语法,可以用SQLAlchemy的text()函数直接写UNION DISTINCT的原生语句,适合一些复杂场景:
from sqlalchemy import text # 直接编写带UNION DISTINCT的原生SQL raw_query = text(""" SELECT id, name FROM table1 UNION DISTINCT SELECT id, name FROM table2 """) with engine.connect() as conn: results = conn.execute(raw_query).fetchall()
不过这种方式会失去ORM的优势,比如表结构变更时需要手动修改SQL,所以更推荐第一种方法。
方法三:设置会话级别的union_default_mode参数
正如你想到的,也可以在会话中先设置union_default_mode为DISTINCT,这样后续所有的UNION查询都会默认使用去重模式:
from sqlalchemy import text, union_all with engine.connect() as conn: # 设置当前会话的默认UNION模式为DISTINCT conn.execute(text("SET union_default_mode = 'DISTINCT'")) # 此时用union_all()生成的查询也会自动变成UNION DISTINCT union_query = union_all(query1, query2) results = conn.execute(union_query).fetchall()
这种方式适合需要批量执行多个UNION DISTINCT查询的场景,不用每次都显式指定。
总结一下,最推荐的是第一种方法,利用SQLAlchemy原生的union()函数,既简洁又符合框架规范,clickhouse-sqlalchemy会自动处理好ClickHouse的语法要求。
备注:内容来源于stack exchange,提问作者Dmitriy Ignatyev
相关产品推荐
相关产品推荐

