惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
V
Vulnerabilities – Threatpost
GbyAI
GbyAI
P
Proofpoint News Feed
L
LINUX DO - 热门话题
P
Palo Alto Networks Blog
A
About on SuperTechFans
T
Tenable Blog
M
MIT News - Artificial intelligence
IT之家
IT之家
I
Intezer
D
DataBreaches.Net
爱范儿
爱范儿
T
Threatpost
C
CERT Recently Published Vulnerability Notes
云风的 BLOG
云风的 BLOG
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
K
Kaspersky official blog
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
Y
Y Combinator Blog
Cyberwarzone
Cyberwarzone
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Darknet – Hacking Tools, Hacker News & Cyber Security
H
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
Spread Privacy
Spread Privacy
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
AWS News Blog
AWS News Blog
博客园 - 聂微东
C
Check Point Blog
S
Securelist
有赞技术团队
有赞技术团队
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
MongoDB | Blog
MongoDB | Blog
D
Docker
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tailwind CSS Blog
L
Lohrmann on Cybersecurity
G
Google Developers Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog

博客园 - 御天六龙

"AV终结者"病毒发作症状及防范措施&和杀毒有关的网页和软件都无法打开或者安装(重装系统后也一样), 如何查看表结构信息 无数据库日志文件恢复数据库方法两则 浅谈数据库设计技巧 恢复被置疑的数据库 update语句更新时我忘了限制条件了 更新了所有纪录 有办法恢复吗? 如何批量加密存储过程? SQL Server数据汇总完全解析 SQL脚本生成的一些BUG 使用ActiveX控件开发网页常见的问题 SQL Server中利用存储过程来高性能地进行分页 Sql server数据库开发常用汇总 小记存储过程中经常用到的本周,本月,本年函数 测试用到的SQL语句 SQL Server中全角和半角字符的比较问题 配置SQL Server 2000选项 数据库主键设计之思考 SQL Sever2000绿色版,告别软件分发时安装SQL的烦恼 数据采集服务程序--ADO连续插入记录,2天后,插入速度明显变慢,求解原因?
老外对T-sql的研究:一个问题多种方法
御天六龙 · 2006-10-01 · via 博客园 - 御天六龙

T-SQL允许你使用不同的方法解决一个问题.有的时候,尽管选择不是那么明显,但是却可以让你得到令人满意的和快乐的惊奇.下边让我们解读Dr. Tom Moreau对同一问题不同的可能性的探索.可能我们可以在那些不同的方法之中发现一些珍贵的东西.

让我们以我们的老朋友Northwind数据库为例,这里我们用到的是[order details]表,这个表是一个定单的明细表,和order表是多对一的关系.也就是一个定单对应多个订购的产品.假设你想得到每个定单订购的总价值,但是不包括59号产品.Listing 1给了我们第一种解法:

select
OrderID,sum (Quantity * UnitPrice) value
from [Order Details] o1 where ProductID <> 59
group by OrderID

上边的语句很简单,它排除掉了59号产品的定单明细条目,然后进行分组统计.但是如果我们需要忽略掉订购59号产品的定单呢?也就是说我们要统计没有包含59号产品的定单的价值.你想到了WHERE, NOT EXIST(S)关键词了吗?Listing 2给了我们第二种方法:

select
o1.OrderID,sum (o1.Quantity * o1.UnitPrice) value
from [Order Details] o1
where not exists
(
select
*
from [Order Details] o2
where
o2.OrderID = o1.OrderID
and o2.ProductID = 59
)
group by o1.OrderID

如果你不喜欢用exist的话,你可以转化成使用not in:

Listing 3
select
o1.OrderID,sum (o1.Quantity * o1.UnitPrice) value
from [Order Details] o1
where 59 not in
(
select ProductID from
[Order Details] o2
where o2.OrderID = o1.OrderID
)
group by o1.OrderID

尽管Listing 1不满足我们现在的查询条件.但是从性能发面考虑,Listing 1还是最好的,因为它只用到了一次表的扫描.而后边的两个查询都是用到了相关子查询,如果你查看查询计划就回看到,他们都涉及到了两次表的扫描.如果你曾经在 T-SQL用过交叉表查询的话,你就不会对聚集函数里边的case结构陌生.现在我们就把这个非常有趣的方法应用到我们的问题中来:

Listing 4
select
OrderID,sum (Quantity * UnitPrice) value
from
[Order Details] o1
group by OrderID
having
sum (case when ProductID = 59 then 1 else 0 end) = 0

HAVING子句起到了对分组的结果进行过滤的作用.如果没有包含59号产品,就会出现0=0,显然这是满足条件的.如果包含了59号产品的订购,就会出现n=0(n<>0),这样的定单就回被过滤掉.查看执行计划你就回发现是一次表的扫描,非常棒!

再来举一个例子:我们这回用到的表是order表,假设我们要统计只通过一个雇员雇员下定单的顾客.你可以想到用子查询not exist来实现:

select distinct
o1.CustomerID
from
Orders o1
where not exists
(
select * from Orders o2
where o2.CustomerID = o1.CustomerID
and o2.EmployeeID <> o1.EmployeeID
)

同样的,这个语句可以通过带有HAVING子句的分组来实现.

Listing 6
select CustomerID from
Orders group by CustomerID
having
min (EmployeeID) = max (EmployeeID)

另一种方法:

Listing 7
select CustomerID from
Orders group by CustomerID
having
count (distinct EmployeeID) = 1

Listing 6和Listing 7查询消耗都要小于Listing 5.相比Listing 5的两次表扫描,他们只进行一次表的扫描.而Listing 6的损耗还要稍微小于Listing 7.但是,Listing 7的一个显著的特点就是它可以适应到一个顾客对应两个雇员,三个雇员......

其实大家可能现在明白了这篇文章将的是什么?它就是教我们怎么用having 子句来达到过滤组的目的.可以达到避免两次表扫描的目的.可以达到更高的性能.我从这篇文章学到了很多的方法,你呢?