请教一个SQL的优化问题,关于内嵌的查询。

jadesun 2011-06-13 09:25:25
原SQL如下:


SELECT cniId,
(SELECT TOP 1 cnvcLeadOrganCname FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId) AS cnvcLeadOrganCname,
(SELECT TOP 1 cnvcSpeedName FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId ORDER BY tbA.cniId DESC) AS cnvcSpeedName,
(SELECT TOP 1 cnvcSpeed FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId ORDER BY tbA.cniId DESC) AS cnvcSpeed,
(SELECT TOP 1 cndSpeedTime FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId ORDER BY tbA.cniId DESC) AS
FROM tbCommonPart


这个SQL中,反复的查询了tbApproval表。而tbApproval表的数据很大,从执行分析来看,tbApproavl的查询已经用了键查找。

请教一下大家怎么优化这样的内嵌语句才能达到最好的性能。
...全文
141 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
jadesun 2011-06-14
  • 打赏
  • 举报
回复
请问一下还有什么办法可以优化这个查询吗?
jadesun 2011-06-14
  • 打赏
  • 举报
回复
把SQL语句再次简化成上面两位兄弟的,然后查看执行的效率

SET STATISTICS IO ON
SET STATISTICS TIME ON

SELECT c.cniId, p.cniCommonPartId FROM tbCommonPart c
JOIN tbApproval p ON c.cniId = p.cniCommonPartId
where not exists (select 1 from tbApproval where cniCommonPartId = p.cniCommonPartId and cniId > p.cniId)

SET STATISTICS IO OFF
SET STATISTICS TIME OFF


(61437 行受影响)
表 'tbCommonPart'。扫描计数 61439,逻辑读取 123131 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 58309,逻辑读取 1045154 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'tbApproval'。扫描计数 2,逻辑读取 898 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
CPU 时间 = 1687 毫秒,占用时间 = 1801 毫秒。

SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
jadesun 2011-06-14
  • 打赏
  • 举报
回复
感谢zy112429和cd731107的回复,你们的思路给我了一个新的选择。但是这样写的性能很差

根据你们的写法,SQL语句改成这样。但是查询的时间长达1分多中。tbCommonpart表70W的记录,tbApproval表的记录有200多W。

SELECT tbAA.cniId, tbAA.cnvcTitle, tbAA.cndSendTime, tbAA.cnvcSecretaryKind, tbAA.cnvcSecName, tbAA.cnvcSendEname, tbAA.cnvcSendCname,
tbAP.cnvcSendOrganCname, tbAA.cnvcSendOrganId, tbAA.cnvcSecretaryKind, tbAA.cnvcEndflag, tbAA.cnvcFileType
FROM tbCommonPart tbAA JOIN (SELECT DISTINCT (tbApproval.cniCommonPartId) AS cniId
FROM tbCommonPart JOIN
tbApproval ON tbCommonPart.cniId = tbApproval.cniCommonPartId
WHERE tbCommonPart.cnvcDeleteFlag = '0' AND tbApproval.cnvcReturnFlag = '0') tbAB ON tbAA.cniId = tbAB.cniId
JOIN tbCompany tbAC ON tbAA.cnvcSendOrganId = tbAC.cniNodeID
JOIN tbApproval tbAP on tbAA.cniId = tbAP.cniCommonPartId

WHERE not exists(select 1 from tbApproval where cniCommonPartId=tbAP.cniCommonPartId and cniId>tbAP.cniId)
and tbAC.cnvcOrganID LIKE '%0-1-%' AND tbAA.cndSendTime BETWEEN '2011-3-15 00:00:00' AND '2011-6-13 23:59:59'
ORDER BY cnvcSpeed DESC,cndSpeedTime asc, tbAA.cnvcSecretaryKind DESC, tbAA.cndSendTime DESC
GoAwayZ 2011-06-13
  • 打赏
  • 举报
回复
SELECT a.cniId, a.cndSpeedTime, a.OweStatus,a.cnvcFileName,
b.cnvcLeadOrganCname,b.cnvcSpeedName,b.cnvcSpeed,b.cndSpeedTime
FROM tbCommonPart a left join tbApproval b on a.cniId=b.cniCommonPartId
and not exists(select 1 from tbApproval
where cniCommonPartId=b.cniCommonPartId and cniId>b.cniId)
jadesun 2011-06-13
  • 打赏
  • 举报
回复
对不起大家,我为了简化语句,给了大家误导。语句改成如下的方式:


SELECT cniId, cndSpeedTime, OweStatus,cnvcFileName,
(SELECT TOP 1 cnvcLeadOrganCname FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId) AS cnvcLeadOrganCname,
(SELECT TOP 1 cnvcSpeedName FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId ORDER BY tbA.cniId DESC) AS cnvcSpeedName,
(SELECT TOP 1 cnvcSpeed FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId ORDER BY tbA.cniId DESC) AS cnvcSpeed,
(SELECT TOP 1 cndSpeedTime FROM tbApproval AS tbA WHERE tbCommonPart.cniId = tbA.cniCommonPartId ORDER BY tbA.cniId DESC) AS
FROM tbCommonPart
jadesun 2011-06-13
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qianjin036a 的回复:]
你这段语句有问题.
并且这段语句完全可以改为:

SQL code
select top 1 cniCommonPartId,cnvcLeadOrganCname,cnvcSpeedName,cnvcSpeed,cndSpeedTime
from tbApproval order by cniCommonPartId

另一个叫什么tbCommonPart的表在你的查询语句里根本没用……
[/Quote]

tbCommonPart表中还有其它的字段在里面使用,比如cniId,就需要显示出来。
Lyongt 2011-06-13
  • 打赏
  • 举报
回复

Select Top 1 TA.cniId, TB.cnvcLeadOrganCname, TB.cnvcSpeedName, TB.cnvcSpeed, TB.cndSpeedTime
From tbCommonPart TA, tbApproval TB
Where TA.cniId = TB.cniCommonPartId
Order By TB.cniId
--小F-- 2011-06-13
  • 打赏
  • 举报
回复
---TRY
select
a.cniid,
max(b.cnvcLeadOrganCname),
min(b.cnvcSpeedName),
min(cnvcSpeed),
min(cndSpeedTime )
from
tbCommonPart a,tbApproval b
where
a.cniId = b.cniCommonPartId
group by
a.cniid
cd731107 2011-06-13
  • 打赏
  • 举报
回复

select b.cniId,a.cnvcLeadOrganCname,a.cnvcSpeedName,a.cnvcSpeed,a.cndSpeedTime
FROM tbApproval a, tbCommonPart b
where a.cniCommonPartId= b.cniId
and not exists
(select 1 from tbApproval c where c.cniId>a.cniId)
-晴天 2011-06-13
  • 打赏
  • 举报
回复
你这段语句有问题.
并且这段语句完全可以改为:
select top 1 cniCommonPartId,cnvcLeadOrganCname,cnvcSpeedName,cnvcSpeed,cndSpeedTime
from tbApproval order by cniCommonPartId

另一个叫什么tbCommonPart的表在你的查询语句里根本没用,除非这段语句你是从一大堆语句中摘出来的一小段.
ycproc 2011-06-13
  • 打赏
  • 举报
回复
你这个查询实在 太庞大了

用内联吧

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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