UNION和UNION ALL的用法与区别

前言

MySQL中,可以使用UNIONUNION ALL查询多多条结果,并且它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同

使用

1、 建立light_devcice

 

sql

代码解读

复制代码

SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for light_device -- ---------------------------- DROP TABLE IF EXISTS `light_device`; CREATE TABLE `light_device` ( `id` bigint NOT NULL AUTO_INCREMENT, `tenant_id` bigint NULL DEFAULT NULL COMMENT '租户ID', `org_id` bigint NOT NULL COMMENT '机构ID', `host_id` bigint NOT NULL COMMENT '网关设备ID', `device_id` bigint NOT NULL COMMENT '设备ID', `parent_device_id` bigint NULL DEFAULT NULL COMMENT '父设备ID', `device_name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '设备名称', `device_remark` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '设备备注', `device_sn` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '设备唯一标识', `device_type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '设备类型', `device_category` int NULL DEFAULT NULL COMMENT '设备分类', `region_id` bigint NULL DEFAULT NULL COMMENT '区域ID', `display_flag` tinyint NULL DEFAULT 1 COMMENT '是否显示(网关):1>显示;0>不显示', `terminal_flag` tinyint NULL DEFAULT 0 COMMENT '带终端设备能力:1>是;0>否', `control_flag` tinyint NULL DEFAULT 0 COMMENT '控制能力:1>是;0>否', `delete_flag` tinyint NULL DEFAULT 0 COMMENT '是否删除:1:是;0否', `create_by` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '创建人', `update_by` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '更新人', `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `saas_device_id` bigint NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `device_id_UNIQUE`(`device_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1899370485329244162 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC; SET FOREIGN_KEY_CHECKS = 1;

2、建立light_device_property

 

sql

代码解读

复制代码

SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for light_device_property -- ---------------------------- DROP TABLE IF EXISTS `light_device_property`; CREATE TABLE `light_device_property` ( `id` bigint NOT NULL AUTO_INCREMENT, `tenant_id` bigint NULL DEFAULT NULL COMMENT '租户ID', `org_id` bigint NOT NULL COMMENT '机构ID', `host_id` bigint NULL DEFAULT NULL COMMENT '网关ID', `device_sn` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '设备唯一标识', `device_id` bigint NOT NULL COMMENT '设备ID', `device_key` int NOT NULL COMMENT '设备属性ID', `property_name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '属性名称', `property_remark` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '设备备注', `display_flag` tinyint NULL DEFAULT 1 COMMENT '是否显示(网关):1>显示;0>不显示', `delete_flag` tinyint NULL DEFAULT 0 COMMENT '是否删除:1:是;0否', `region_id` bigint NOT NULL COMMENT '区域ID', `create_by` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '创建人', `update_by` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '更新人', `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `load_dev_type` int NULL DEFAULT NULL COMMENT '终端设备类型:开关量输入设备、继电器输出设备类型、无线终端设备类型。', `saas_device_id` bigint NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1897904309122183171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC; SET FOREIGN_KEY_CHECKS = 1;

使用union查询

 

css

代码解读

复制代码

select p.id as propertyId, p.device_id as deviceId, p.property_name as deviceName, p.device_key as deviceKey, p.property_remark as deviceRemark, p.host_id as hostId, p.load_dev_type as deviceType, p.display_flag as display, p.saas_device_id as saasDeviceId from light_device_property p where p.org_id = 1853960415193595905 union select p.id as propertyId, p.device_id as deviceId, p.device_name as deviceName, null as deviceKey, p.device_remark as deviceRemark, p.host_id as hostId, p.device_type as deviceType, p.display_flag as display, p.saas_device_id as saasDeviceId from light_device p where p.org_id = 1853960415193595905

返回值为

如果使用该sql

 

csharp

代码解读

复制代码

select p.id as propertyId from light_device_property p where p.org_id = 1853960415193595905 union select p.id as propertyId from light_device p where p.org_id = 1853960415193595905

会发现如果两个表有重复id,不会出现重复记录

 

css

代码解读

复制代码

select p.id as propertyId from light_device_property p where p.org_id = 1853960415193595905 union all select p.id as propertyId from light_device p where p.org_id = 1853960415193595905

会发现如果两个表有重复id,会出现重复记录

总结

UNION 从查询结果集中自动去除了重复的行,如果要返回所有匹配行,而不进行删除,可以使用 UNION ALL。

### 使用 SQLAlchemy 实现递归查询 为了实现递归查询,在 SQL 中通常会使用 Common Table Expressions (CTE),也称为 WITH 查询。SQLAlchemy 支持 CTEs,这使得编写递归查询变得可能[^1]。 #### 创建递归查询的例子 下面是一个简单的例子,展示了如何通过 SQLAlchemy 来创建一个递归查询。此示例假设有一个自引用表 `employee` 表示公司员工及其上级的关系: ```python from sqlalchemy import create_engine, Column, Integer, String, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy.sql import select, func from sqlalchemy import text Base = declarative_base() class Employee(Base): __tablename__ = 'employees' id = Column(Integer, primary_key=True) name = Column(String(50)) manager_id = Column(Integer, ForeignKey('employees.id')) reports = relationship("Employee", lazy='joined', join_depth=2) engine = create_engine('sqlite:///:memory:') Session = sessionmaker(bind=engine) session = Session() Base.metadata.create_all(engine) def recursive_query(): cte = ( select([Employee]) .where(Employee.manager_id.is_(None)) # Root nodes have no parent. .cte(name="tree", recursive=True) ) child_alias = aliased(Employee, name="child") tree_alias = aliased(cte, name="parent") rec_part = ( select([ child_alias ]) .join(tree_alias, child_alias.manager_id == tree_alias.c.id) ) union_cte = cte.union_all(rec_part).alias('union_tree') result = session.query(Employee.name).select_entity_from( union_cte.order_by(text('id'))).all() return result ``` 这段代码首先定义了一个名为 `Employee` 的 ORM 类,它代表了一张存储员工信息以及他们直接上司 ID 的表格。接着构建了一个递归公用表达式 (`WITH RECURSIVE`) ,用于从根节点(即那些没有经理的员工)开始迭代地获取所有的子节点直到树的最后一层。最后执行这个查询并将结果返回给调用者。 请注意,实际应用中应当根据具体的业务逻辑调整上述代码片段中的细节部分,比如连接字符串、字段名等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值