在最近的工作中遇到一个问题,要将两个字段相似的表里的数据统一起来展示在一个统计页面中。如果是单纯的展示数据那很简单,两个表查出来之后组合一下就完事了,但是有坑的地方就是分页和按照时间搜索,这两个功能决定了不可能单独查询两张表。在同事的建议下,使用了union的联合查询,最终完成这个功能。做一个简单的demo,记录下这个功能。

数据库和sqlalchemy安装请参考另一篇文章 sqlalchemy数据库查询小集合

定义数据表

定义 两张表,字段类型相同,但名称不同。

#coding:utf-8

from sqlalchemy import Column,CHAR,INTEGER
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker Base = declarative_base() class User(Base):
__tablename__ = "user" id = Column(CHAR(20),primary_key = True)
name = Column(CHAR(20))
age = Column(INTEGER) class Teacher(Base):
__tablename__ = "teacher" id = Column(CHAR(20),primary_key = True)
tec_name = Column(CHAR(20))
tec_age = Column(INTEGER) engine = create_engine('mysql+mysqldb://root:12345678@localhost:3306/test') def create_table(table_name):
table_name.metadata.create_all(engine)
print "创建成功" def insert_data(): DBSession = sessionmaker(bind=engine)
session = DBSession()
for x in range(10):
temp = {}
temp['id'] = x
temp['name'] = 'user_' + str(x)
temp['age'] = x
user = User(**temp)
session.add(user) for x in range(15):
temp = {}
temp['id'] = x
temp['tec_name'] = 'tec_' + str(x)
temp['tec_age'] = x * 2
tec = Teacher(**temp)
session.add(tec) session.commit()
session.close()
print 'success' if __name__ = '__main__':
create_table(User)
create_table(Teacher)
insert_data()

User表字段:

mysql> desc user;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id | char(20) | NO | PRI | NULL | |
| name | char(20) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

User表数据:

mysql> select * from user;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 0 | user_0 | 0 |
| 1 | user_1 | 1 |
| 2 | user_2 | 2 |
| 3 | user_3 | 3 |
| 4 | user_4 | 4 |
| 5 | user_5 | 5 |
| 6 | user_6 | 6 |
| 7 | user_7 | 7 |
| 8 | user_8 | 8 |
| 9 | user_9 | 9 |
+----+--------+------+
10 rows in set (0.00 sec)

Teacher表字段:

mysql> desc teacher;
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| id | char(20) | NO | PRI | NULL | |
| tec_name | char(20) | YES | | NULL | |
| tec_age | int(11) | YES | | NULL | |
+----------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec) mysql>  

teacher表数据:

mysql> select * from teacher;
+----+----------+---------+
| id | tec_name | tec_age |
+----+----------+---------+
| 0 | tec_0 | 0 |
| 1 | tec_1 | 2 |
| 10 | tec_10 | 20 |
| 11 | tec_11 | 22 |
| 12 | tec_12 | 24 |
| 13 | tec_13 | 26 |
| 14 | tec_14 | 28 |
| 2 | tec_2 | 4 |
| 3 | tec_3 | 6 |
| 4 | tec_4 | 8 |
| 5 | tec_5 | 10 |
| 6 | tec_6 | 12 |
| 7 | tec_7 | 14 |
| 8 | tec_8 | 16 |
| 9 | tec_9 | 18 |
+----+----------+---------+
15 rows in set (0.00 sec)

查询

首先做一个简单的查询,将两个表的数据分别查出来

def select():

    DBSession = sessionmaker(bind=engine)
session = DBSession()
table_data = session.query(User).all()
session.close() for x in table_data:
print x.name,'------>',x.age table_data = session.query(Teacher).all()
session.close()
for x in table_data:
print x.tec_name,'------>',x.tec_age

查询结果:

 Desktop  python union_one.py
/home/ljk/.local/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py:2514: Warning: '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead
cursor.execute('SELECT @@tx_isolation')
user_0 ------> 0
user_1 ------> 1
user_2 ------> 2
user_3 ------> 3
user_4 ------> 4
user_5 ------> 5
user_6 ------> 6
user_7 ------> 7
user_8 ------> 8
user_9 ------> 9
-----------------------------------
tec_0 ------> 0
tec_1 ------> 2
tec_10 ------> 20
tec_11 ------> 22
tec_12 ------> 24
tec_13 ------> 26
tec_14 ------> 28
tec_2 ------> 4
tec_3 ------> 6
tec_4 ------> 8
tec_5 ------> 10
tec_6 ------> 12
tec_7 ------> 14
tec_8 ------> 16
tec_9 ------> 18

union查询

union 查询的关键字是 union ,首先将第一张表的数据全部查询出来,然后将第二张表的数据全部查询出来,最后将两个数据使用union联合成一张新表,这张新表可以再次被筛选过滤,分页等。

def select():

    DBSession = sessionmaker(bind=engine)
session = DBSession()
table_data = session.query(User).all()
session.close() # for x in table_data:
# print x.name,'------>',x.age # table_data = session.query(Teacher).all()
# session.close()
# for x in table_data:
# print x.tec_name,'------>',x.tec_age user_data = session.query(User.name,User.age)
tec_data = session.query(Teacher.tec_name.label('name'), Teacher.tec_age.label('age')) result = user_data.union_all(tec_data)
for x in result:
print x.name,'------>',x.age

在上面的查询中需要有一个注意点就是label,可以看到tec_data的查询语句中使用了label这个属性,该属性的作用是将Teacher这张表查询出来的tec_name 字段名称变成name,已达到和User表字段的统一,只有两张表的字段名称一致,类型一致的情况下才能联合查询。

另外还使用了一个union_all 字段,该字段的意思是如果两张表存在相同的记录也要全部展示出来,想要让相同的记录合并起来使用union即可

查询结果如下:

 Desktop  python union_one.py
/home/ljk/.local/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py:2514: Warning: '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead
cursor.execute('SELECT @@tx_isolation')
user_0 ------> 0
user_1 ------> 1
user_2 ------> 2
user_3 ------> 3
user_4 ------> 4
user_5 ------> 5
user_6 ------> 6
user_7 ------> 7
user_8 ------> 8
user_9 ------> 9
tec_0 ------> 0
tec_1 ------> 2
tec_10 ------> 20
tec_11 ------> 22
tec_12 ------> 24
tec_13 ------> 26
tec_14 ------> 28
tec_2 ------> 4
tec_3 ------> 6
tec_4 ------> 8
tec_5 ------> 10
tec_6 ------> 12
tec_7 ------> 14
tec_8 ------> 16
tec_9 ------> 18

往往查询出来还不是最终目的,还需要对查询出来的数据过滤。查询出来的数据不是一张正真的表,如果使用字段去匹配过滤条件呢?以查询出age 大于 5为例 ,有两种过滤方式:

1.使用User.age 作为筛选条件

2.使用Teacher.age 作为筛选条件

规则就是使用两张表里任意一张表的原始字段过滤即可,该过滤条件会在联合查询出来的结果起上作用。

使用 User 表字段

def select():

    DBSession = sessionmaker(bind=engine)
session = DBSession()
table_data = session.query(User).all()
session.close() # for x in table_data:
# print x.name,'------>',x.age # table_data = session.query(Teacher).all()
# session.close()
# for x in table_data:
# print x.tec_name,'------>',x.tec_age user_data = session.query(User.name,User.age)
tec_data = session.query(Teacher.tec_name.label('name'), Teacher.tec_age.label('age')) # result = user_data.union_all(tec_data)
# for x in result:
# print x.name,'------>',x.age result = user_data.union_all(tec_data).filter(User.age > 5) for x in result:
print x.name,'------>',x.age

 Desktop  python union_one.py
/home/ljk/.local/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py:2514: Warning: '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead
cursor.execute('SELECT @@tx_isolation')
user_6 ------> 6
user_7 ------> 7
user_8 ------> 8
user_9 ------> 9
tec_10 ------> 20
tec_11 ------> 22
tec_12 ------> 24
tec_13 ------> 26
tec_14 ------> 28
tec_3 ------> 6
tec_4 ------> 8
tec_5 ------> 10
tec_6 ------> 12
tec_7 ------> 14
tec_8 ------> 16
tec_9 ------> 18

使用 Teacher 表字段

def select():

    DBSession = sessionmaker(bind=engine)
session = DBSession()
table_data = session.query(User).all()
session.close() # for x in table_data:
# print x.name,'------>',x.age # table_data = session.query(Teacher).all()
# session.close()
# for x in table_data:
# print x.tec_name,'------>',x.tec_age user_data = session.query(User.name,User.age)
tec_data = session.query(Teacher.tec_name.label('name'), Teacher.tec_age.label('age')) result = user_data.union_all(tec_data).filter(Teacher.tec_age>5) for x in result:
print x.name,'------>',x.age
 Desktop  python union_one.py
/home/ljk/.local/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py:2514: Warning: '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead
cursor.execute('SELECT @@tx_isolation')
user_6 ------> 6
user_7 ------> 7
user_8 ------> 8
user_9 ------> 9
tec_10 ------> 20
tec_11 ------> 22
tec_12 ------> 24
tec_13 ------> 26
tec_14 ------> 28
tec_3 ------> 6
tec_4 ------> 8
tec_5 ------> 10
tec_6 ------> 12
tec_7 ------> 14
tec_8 ------> 16
tec_9 ------> 18

关于union联合查询有一个说法很形象:join查询就像是横向扩展,将多张表的数据横向组合在一起,而union像是纵向扩展,将多张表数据纵向排列起来

sqlalchemy union 联合查询的更多相关文章

  1. [办公自动化] 再读《让EXCEL飞》(从excel导入access数据时,union联合查询,数据源中没有包含可见的表格)

    一年多以前就买了@Mrexcel的<让excel飞>这本书.整体思路是利用access结合excel,大幅度提高数据分析效率. 最近又拿出来看了看.第十五章,比高级筛选更“高级”,P241 ...

  2. day20 关联查询与多表联查 & 子查询与union联合查询 & 数据库定义语言DDL

    day20 关联查询 #左连接:表名 left join 表名 以左表为主表,只显示与左表能匹配的行 SELECT s.*,q.* FROM student AS s LEFT JOIN queue_ ...

  3. VBA+SQL transform pivot union联合查询的基础应用

    Sub 项目状态查询() '如果“项目状态”是未转运营那么实施状态是不能选择的,因为还没有实施.'如果“项目状态”选择状态后,那么项目名称里面只显示该状态的项目名称.如果“项目状态”选择的不是未转运营 ...

  4. SqlSever基础 union 联合查询,厉害的并集 重复项只显示一个 两个查询结果并在一起后排序

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  5. laravel4.2 union联合,join关联分组查询最新记录时,查询条件不对,解决方案

    需求: 分组联合查询,或者最新记录. 问题:  mysql分组的时候默认会查询第一条记录,存在gourp by时 order by 无效. 一般解决办法就是 ,select * from ( sele ...

  6. Mysql的联合查询

    联合查询 union联合查询 语法:     select 语句 union [all|distinct] select 语句; 示例: 特点:     条件:两表的查询出来的字段数目必须相同     ...

  7. Mysql连接查询、子查询、联合查询 整理

    连接查询 连接语法的基本形式 from 表1  [连接方式]  join 表2  [on 连接条件]: 交叉连接 语法: from  表1  [cross]  join  表2  ;      //可 ...

  8. MySQL开发——【联合查询、多表连接、子查询】

    联合查询 所谓的联合查询就是将满足条件的结果进行拼接在同一张表中. 基本语法: select */字段 from 数据表1 union [all | distinct] select */字段 fro ...

  9. (五)连接查询(SQL99标准)、子查询、分页查询、联合查询

    一.连接查询(SQL99标准) 1.含义:当要查询的数据来自多张表时要使用连接查询 2.语法: select 查询列表 from 表1 别名 [连接类型] join 表2 别名 on 连接条件 [wh ...

  10. SQL语句(六)分页查询和联合查询

    目录 一.分页查询 语法格式 应用 二.联合查询 语法和作用 特点 应用 UNION和UNION ALL的区别 一.分页查询 语法格式 SELECT 查询列表 FROM 表 WHERE ... GRO ...

随机推荐

  1. Newbie_calculations

    拿到这道题是个应用程序,经过上次的经验就跟程序交互了一下,结果根本交互不了,输入什么东西都没有反应 然后打开ida分析发现有几个函数还有一堆的操作数,看到这一堆东西就没心思分析了,后面才知道原来就是要 ...

  2. Mybatis和其他主流框架的整合使用

    Mybatis简介 MyBatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google ...

  3. 暴力+分治+贪心+DP:最大子序列和

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 ...

  4. 升级到 Pulsar3.0 后深入了解 JWT 鉴权

    背景 最近在测试将 Pulsar 2.11.2 升级到 3.0.1的过程中碰到一个鉴权问题,正好借着这个问题充分了解下 Pulsar 的鉴权机制是如何运转的. Pulsar 支持 Namespace/ ...

  5. 基于.net6.0 Fast.ORM 已全面支持AOT编译 所有Api均测试通过

    Fast Framework 作者 Mr-zhong 代码改变世界.... 一.前言 Fast Framework 基于NET6.0 封装的轻量级 ORM 框架 支持多种数据库 SqlServer O ...

  6. xv6:labs2 syscall

    lab2 1.lab2的内容总结:关于系统调用整个跟踪过程: 使用系统调用时,用户态会通过软中断(trap,陷阱)进入内核中,由trap识别中断来自系统调用,然后调用syscall函数, 跟踪过程: ...

  7. Net 高级调试之一:开始认识一些调试工具

    当进行网络高级调试时,使用合适的工具可以帮助我们更深入地了解问题所在,并提供有效的解决方案.下面是一些常用的网络调试工具,以及它们的功能和用法. 1. Wireshark:Wireshark是一个流行 ...

  8. git推送时报错:fatal: unable to access 'https://github.com/xxx/xxx.git/': Failed to connect to 127.0.0.1 port 31181 after 2063 ms: Connection refused

    一.报错原因 1.因为git在拉取或者提交项目时,中间会有git的http和https代理,但是我们本地环境本身就有SSL协议了,所以取消git的https代理即可,不行再取消http的代理. 2.当 ...

  9. Netty源码学习9——从Timer到ScheduledThreadPoolExecutor到HashedWheelTimer

    系列文章目录和关于我 一丶前言 之前在学习netty源码的时候,经常看netty hash时间轮(HashedWheelTimer)的出现,时间轮作为一种定时调度机制,在jdk中还存在Timer和Sc ...

  10. GIS系统想要实现Cesium For Unreal的视觉效果是否有捷径可走?

    对于大多数GIS开发人员来说,CesiumJS都是比较熟悉的引擎,但是相比较Cesium For Unreal而言,CesiumJS的视觉效果就显得差强人意了,因此一些GIS开发人员对Cesium F ...