select(select from table_a ) from table_b 嵌套语句解析

本文探讨了为何在SQL中使用嵌套select count()语句会返回多个结果,类似于group by的效果,并通过实例分析了其与标准group by的区别。通过创建表和示例代码,揭示了这种结构的实际应用和背后的原理。

 

今天遇到一个问题

这是下面的例句:

select (select count(b1.name) from table_b where a1.id=b1.id 
and ···)from table_1 a1 where ···

大致就是这样的一个句子

但是最后返回的count()居然不是一个值,而是一个很多结果的集合

正常的select count() from table where ···返回的就是一个值啊?

为什么这么写呢?有什么意义呢?

下面创建俩个表

表#a_aa_a、#a_aa_b

create table #a_aa_a(
t_id int,
t_name varchar(10),
t_date int,
t_grade int
)
insert into #a_aa_a VALUES  (132154,'盲僧',20210401,1)
insert into #a_aa_a VALUES  (231654,'盲僧',20210403,2)--
insert into #a_aa_a VALUES  (236587,'盲僧',20210405,3)
insert into #a_aa_a VALUES  (365214,'亚索',20210401,1)
insert into #a_aa_a VALUES  (365214,'亚索',20210403,2)--
insert into #a_aa_a VALUES  (325412,'亚索',20210405,3)
insert into #a_aa_a VALUES  (365584,'盖伦',20210401,1)
insert into #a_aa_a VALUES  (236587,'盖伦',20210403,2)--
insert into #a_aa_a VALUES  (326985,'盖伦',20210408,3)
create table #a_aa_b(
t_id int,
t_name varchar(10),
t_grade int
)
insert into #a_aa_b VALUES  (132154,'盲僧',3)
insert into #a_aa_b VALUES  (231654,'盲僧',8)
insert into #a_aa_b VALUES  (236587,'盲僧',6)
insert into #a_aa_b VALUES  (365214,'亚索',5)
insert into #a_aa_b VALUES  (365214,'亚索',2)--
insert into #a_aa_b VALUES  (325412,'亚索',1)
insert into #a_aa_b VALUES  (365584,'盖伦',10)
insert into #a_aa_b VALUES  (236587,'盖伦',2)--
insert into #a_aa_b VALUES  (326985,'盖伦',23)

按上述例子,得到相同情景下的select嵌套语句

select (select count(t_id) from #a_aa_b b where a.t_name = b.t_name 
and a.t_grade=b.t_grade ) from #a_aa_a a where t_grade=2

经过试验,其实这个嵌套语句的功能就是分组,类似于group by b.t_id,为什么说是类似呢,因为group by 语句是不会返回空的值的,为空的数据不会显示,但是select嵌套语句会显示出来

与上述语句同等力效的语句

select count(b.t_id) from #a_aa_b b inner join #a_aa_a a 
on a.t_name = b.t_name and a.t_grade=b.t_grade and a.t_grade=2 group by a.t_id

俩语句结果对比--(筛选数据为创建表语句后面有--的数据)

select嵌套语句结果图:

常规group by语句结果图

不需要计算为0数据情况,二者皆可使用

 

 

<think>我们正在讨论SQLite中获取表结构信息的两种方法:`SELECT * FROM pragma_table_info('table_name');` 和 `PRAGMA table_info('table_name');` 根据引用内容,PRAGMA是SQLite特有的命令,用于修改操作或查询内部数据。它不同于标准的SQL语句。 首先,`PRAGMA table_info('table_name');` 是直接使用PRAGMA命令来查询表的信息。这是SQLite提供的一种特殊方式。 其次,`SELECT * FROM pragma_table_info('table_name');` 则是将`pragma_table_info`作为一个表值函数(table-valued function)来使用,这样它就可以在SELECT语句中像表一样被查询。 区别: 1. 语法不同:一个是PRAGMA命令,另一个是SELECT语句。 2. 使用场景:PRAGMA命令是SQLite特有的,而将pragma作为表值函数使用则允许在更复杂的查询中与其他表连接或使用WHERE子句等。 3. 兼容性:PRAGMA命令在SQLite的早期版本中就存在,而表值函数形式的pragma是在SQLite 3.16.0 (2017-01-02) 版本中引入的(根据SQLite的文档,但具体版本可能需查证,不过这里不是重点)。 因此,如果你只需要获取表的基本结构信息,两种方式都可以。但如果你需要将表结构信息与其他表进行关联查询,那么使用表值函数的形式会更加灵活。 例如,你可以这样使用表值函数形式: SELECT * FROM pragma_table_info('table1') WHERE name NOT IN (SELECT name FROM pragma_table_info('table2')); 而PRAGMA命令则不能直接用于子查询或连接。 另外,根据引用[1]中的说明,PRAGMA命令可能在sqlite3_prepare阶段就执行了(取决于具体的pragma和SQLite版本),而表值函数形式则是在执行时(sqlite3_step)才运行。 总结: - `PRAGMA table_info('table_name');` 是传统的专用语法。 - `SELECT * FROM pragma_table_info('table_name');` 是较新的表值函数形式,可以嵌入到更复杂的SQL查询中。 注意:在表值函数形式中,表名作为参数传入,而在PRAGMA命令中,表名也可以作为字符串参数传入(注意单引号)。 参考引用[1]中关于PRAGMA的说明,它提到PRAGMA是SQLite特有的,且可能在不同版本中有所变化。因此,使用表值函数形式可能需要较新的SQLite版本。 最后,根据引用[3](虽然讲的是user_version,但属于同一类pragma),pragma可以获取或设置内部数据。 所以,两种方法都可以用来获取表结构,但表值函数形式更灵活,特别是在需要与其他数据结合查询时。</think>在 SQLite 中,`PRAGMA table_info` 和 `SELECT * FROM pragma_table_info` 都是用于获取表结构信息的方法,但它们在实现机制和使用方式上有重要区别: ### 1. **`PRAGMA table_info('表名')`** - **本质**:SQLite 特有的**编译指示命令**(非标准 SQL),直接访问数据库元数据[^1]。 - **执行阶段**: - 在预处理阶段(`sqlite3_prepare()`)执行,而非标准 SQL 的执行阶段(`sqlite3_step()`)[^1][^2]。 - 结果在查询编译后立即生成,不参与执行计划优化。 - **输出格式**:固定为表格形式,包含列:`cid`(列ID)、`name`(列名)、`type`(数据类型)、`notnull`(非空约束)、`dflt_value`(默认值)、`pk`(主键标志)。 - **限制**: - 无法与其他表连接或嵌套在子查询中。 - 只能以独立命令形式执行。 ### 2. **`SELECT * FROM pragma_table_info('表名')`** - **本质**:将编译指示封装为**表值函数**,通过标准 SQL 查询访问[^3]。 - **执行阶段**: - 在 SQL 执行阶段(`sqlite3_step()`)处理,与普通查询行为一致[^2]。 - 可被查询优化器处理。 - **灵活性**: - 支持 `WHERE` 过滤、`JOIN` 连接、子查询等标准 SQL 操作。 - 示例:筛选主键列 ```sql SELECT name, type FROM pragma_table_info('users') WHERE pk > 0; ``` - **兼容性**:需要 SQLite 3.16.0+(2017年发布)。 --- ### 关键区别总结 | **特性** | `PRAGMA table_info` | `SELECT FROM pragma_table_info` | |------------------------|-----------------------------|--------------------------------| | **语法类型** | SQLite 特有命令 | 标准 SQL 查询 | | **执行时机** | 预处理阶段 (`sqlite3_prepare`) | 执行阶段 (`sqlite3_step`) | | **能否嵌套/连接** | ❌ 不支持 | ✅ 支持 | | **输出自定义** | ❌ 固定格式 | ✅ 可筛选列、排序等 | | **最低 SQLite 版本** | 所有版本 | 3.16.0+ (2017) | ### 使用建议 - 简单场景(仅需表结构)→ **`PRAGMA table_info`** - 复杂场景(需连接、过滤或整合其他数据)→ **`SELECT FROM pragma_table_info`** --- ### 相关问题 1. 如何获取 SQLite 表中所有索引的信息? 2. `PRAGMA` 命令与标准 SQL 查询在性能上有何差异? 3. 在其他数据库(如 MySQL 或 PostgreSQL)中如何查询表结构? [^1]: PRAGMA 是 SQLite 特有的命令,在预处理阶段可能执行,行为与标准 SQL 不同。 [^2]: `sqlite3_prepare` 和 `sqlite3_step` 是 SQLite API 的关键阶段,影响 PRAGMA 的执行时机。 [^3]: `pragma_table_info` 作为表值函数,允许通过 SELECT 灵活访问元数据。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值