sql 嵌套子查询

qq_21044655 2018-08-10 06:05:10
这是sc表

执行下面的查询后
select * from (select s# , string_agg(c#, '') as c#value from (select TOP 100 PERCENT * from sc order by c#) as sc2 group by s#) as A

但在最后加上where A.s# = '0001'后,查出来的结果竟然是

为什么会这样,而不是01 02 03

...全文
430 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
string_agg 2017 才有的呢
吉普赛的歌 2018-08-11
  • 打赏
  • 举报
回复
引用 5 楼 qq_21044655 的回复:
明白了,谢谢大神解惑


不客气, 没事就结贴吧
qq_21044655 2018-08-11
  • 打赏
  • 举报
回复
引用 4 楼 吉普赛的歌的回复:
[quote=引用 3 楼 qq_21044655 的回复:]
请问下大神第一种方法为什么把100改小一点就可以了呢 ?


还是用你的数据, 看一下 Top 99.99999 PERCENT 与 Top 100 PERCENT 执行计划的区别:
USE tempdb
GO
IF OBJECT_ID('sc') IS NOT NULL DROP TABLE sc
GO
CREATE TABLE sc(
s# VARCHAR(10),
c# VARCHAR(10),
score INT
)
GO
SET NOCOUNT ON
INSERT INTO sc VALUES ('0001','02',112);
INSERT INTO sc VALUES ('0001','03',23);
INSERT INTO sc VALUES ('0002','01',25);
INSERT INTO sc VALUES ('0001','01',78);
INSERT INTO sc VALUES ('0003','02',87);
INSERT INTO sc VALUES ('0003','03',45);
INSERT INTO sc VALUES ('0004','01',41);
INSERT INTO sc VALUES ('0004','03',78);
INSERT INTO sc VALUES ('0005','01',46);
INSERT INTO sc VALUES ('0005','02',55);
INSERT INTO sc VALUES ('0005','03',69);
GO
---------- 以上为测试数据 ---------------
--1. Top 100 嵌套
SELECT * FROM (
SELECT TOP 100 PERCENT * FROM sc ORDER BY c#
) AS t
--2. Top 100 不嵌套
SELECT TOP 100 PERCENT * FROM sc ORDER BY c#
--3. Top 99 嵌套
SELECT * FROM (
SELECT TOP 99.99 PERCENT * FROM sc ORDER BY c#
) AS t




很明显, 在 Top 100 PERCENT 嵌套查询时, 根本就没执行排序。

你是否知道 SQL Server 这样一个规定? 视图中是不允许排序的
而 嵌套查询 和 视图 其实是一个故事, 都是中间结果集。
视图要排序, 也是只能采用 Top 99.99999999 PERCENT 来变相实现。

这个你要问为什么不允许排序, 那真没什么好说的, 规定就是这样了。
一定要说, 可能是 微软的数据库设计师认为对 整个中间结果集 排序 是不合理的, 后续还要对结果集操作, 中间过程排序没有意义,而且 会增加数据库运算的负担。

这些东西不需要穷究了, 没多大意义。
我在 #2 中 按你原来想法 写的方法1SQL, 你觉得有 方法3 看着那么舒心、高效吗?

简洁、高效才是我们的追求。
真正有意义的是, 根据数据库本身思想来写SQL,尽量避免写嵌套的查询, 尽量让排序放在最外层。[/quote] 明白了,谢谢大神解惑
吉普赛的歌 2018-08-11
  • 打赏
  • 举报
回复
引用 3 楼 qq_21044655 的回复:
请问下大神第一种方法为什么把100改小一点就可以了呢 ?


还是用你的数据, 看一下 Top 99.99999 PERCENT 与 Top 100 PERCENT 执行计划的区别:
USE tempdb
GO
IF OBJECT_ID('sc') IS NOT NULL DROP TABLE sc
GO
CREATE TABLE sc(
s# VARCHAR(10),
c# VARCHAR(10),
score INT
)
GO
SET NOCOUNT ON
INSERT INTO sc VALUES ('0001','02',112);
INSERT INTO sc VALUES ('0001','03',23);
INSERT INTO sc VALUES ('0002','01',25);
INSERT INTO sc VALUES ('0001','01',78);
INSERT INTO sc VALUES ('0003','02',87);
INSERT INTO sc VALUES ('0003','03',45);
INSERT INTO sc VALUES ('0004','01',41);
INSERT INTO sc VALUES ('0004','03',78);
INSERT INTO sc VALUES ('0005','01',46);
INSERT INTO sc VALUES ('0005','02',55);
INSERT INTO sc VALUES ('0005','03',69);
GO
---------- 以上为测试数据 ---------------
--1. Top 100 嵌套
SELECT * FROM (
SELECT TOP 100 PERCENT * FROM sc ORDER BY c#
) AS t
--2. Top 100 不嵌套
SELECT TOP 100 PERCENT * FROM sc ORDER BY c#
--3. Top 99 嵌套
SELECT * FROM (
SELECT TOP 99.99 PERCENT * FROM sc ORDER BY c#
) AS t




很明显, 在 Top 100 PERCENT 嵌套查询时, 根本就没执行排序。

你是否知道 SQL Server 这样一个规定? 视图中是不允许排序的
而 嵌套查询 和 视图 其实是一个故事, 都是中间结果集。
视图要排序, 也是只能采用 Top 99.99999999 PERCENT 来变相实现。

这个你要问为什么不允许排序, 那真没什么好说的, 规定就是这样了。
一定要说, 可能是 微软的数据库设计师认为对 整个中间结果集 排序 是不合理的, 后续还要对结果集操作, 中间过程排序没有意义,而且 会增加数据库运算的负担。

这些东西不需要穷究了, 没多大意义。
我在 #2 中 按你原来想法 写的方法1SQL, 你觉得有 方法3 看着那么舒心、高效吗?

简洁、高效才是我们的追求。
真正有意义的是, 根据数据库本身思想来写SQL,尽量避免写嵌套的查询, 尽量让排序放在最外层。
qq_21044655 2018-08-10
  • 打赏
  • 举报
回复
引用 2 楼 yenange 的回复:
USE tempdb
GO
IF OBJECT_ID('sc') IS NOT NULL DROP TABLE sc
GO
CREATE TABLE sc(
s# VARCHAR(10),
c# VARCHAR(10),
score INT
)
GO
SET NOCOUNT ON
INSERT INTO sc VALUES ('0001','02',112);
INSERT INTO sc VALUES ('0001','03',23);
INSERT INTO sc VALUES ('0002','01',25);
INSERT INTO sc VALUES ('0001','01',78);
INSERT INTO sc VALUES ('0003','02',87);
INSERT INTO sc VALUES ('0003','03',45);
INSERT INTO sc VALUES ('0004','01',41);
INSERT INTO sc VALUES ('0004','03',78);
INSERT INTO sc VALUES ('0005','01',46);
INSERT INTO sc VALUES ('0005','02',55);
INSERT INTO sc VALUES ('0005','03',69);
GO
---------- 以上为测试数据 ---------------


--方法1. 将 Top 100 PERCENT => Top 99.99999 PERCENT
select * from (
select s#, string_agg(c#, '') as c#value
from (select TOP 99.99999 PERCENT * from sc order by c#) as sc2
group by s#
) as A
where A.s# = '0001'
/*
s# c#value
---------- --------
0001 010203
*/

--方法2
select * from (
select s#, string_agg(c#,'') WITHIN GROUP (ORDER BY c# ASC) as c#value
from sc
group by s#
) as A
where A.s# = '0001'
/*
s# c#value
---------- --------
0001 010203
*/

--方法3 去嵌套最简洁版
select s#, string_agg(c#,'') WITHIN GROUP (ORDER BY c# ASC) as c#value
from sc
WHERE s#='0001'
group by s#
/*
s# c#value
---------- --------
0001 010203
*/


请问下大神第一种方法为什么把100改小一点就可以了呢 ?
吉普赛的歌 2018-08-10
  • 打赏
  • 举报
回复
USE tempdb
GO
IF OBJECT_ID('sc') IS NOT NULL DROP TABLE sc
GO
CREATE TABLE sc(
s# VARCHAR(10),
c# VARCHAR(10),
score INT
)
GO
SET NOCOUNT ON
INSERT INTO sc VALUES ('0001','02',112);
INSERT INTO sc VALUES ('0001','03',23);
INSERT INTO sc VALUES ('0002','01',25);
INSERT INTO sc VALUES ('0001','01',78);
INSERT INTO sc VALUES ('0003','02',87);
INSERT INTO sc VALUES ('0003','03',45);
INSERT INTO sc VALUES ('0004','01',41);
INSERT INTO sc VALUES ('0004','03',78);
INSERT INTO sc VALUES ('0005','01',46);
INSERT INTO sc VALUES ('0005','02',55);
INSERT INTO sc VALUES ('0005','03',69);
GO
---------- 以上为测试数据 ---------------


--方法1. 将 Top 100 PERCENT => Top 99.99999 PERCENT
select * from (
select s#, string_agg(c#, '') as c#value
from (select TOP 99.99999 PERCENT * from sc order by c#) as sc2
group by s#
) as A
where A.s# = '0001'
/*
s# c#value
---------- --------
0001 010203
*/

--方法2
select * from (
select s#, string_agg(c#,'') WITHIN GROUP (ORDER BY c# ASC) as c#value
from sc
group by s#
) as A
where A.s# = '0001'
/*
s# c#value
---------- --------
0001 010203
*/

--方法3 去嵌套最简洁版
select s#, string_agg(c#,'') WITHIN GROUP (ORDER BY c# ASC) as c#value
from sc
WHERE s#='0001'
group by s#
/*
s# c#value
---------- --------
0001 010203
*/
二月十六 2018-08-10
  • 打赏
  • 举报
回复
试试这样
SELECT
*
FROM
(
SELECT
s#,
string_agg(c#, '') within group(order by c#) AS c#value
FROM
(
SELECT TOP 100 PERCENT
*
FROM
SC
ORDER BY
c#
) AS sc2
GROUP BY
s#
) AS A;

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧