关于SQLServer2005的学习笔记——子查询

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:
SQL Server 的子查询给人的感觉一向不是很好用, IN 子查询无法实现多列的子查询,很多情况下又需要进行自我的子查询操作,比如取员工的最新订单之类的问题。以下 SQL 和案例来之于 <SQLServer2005 技术内幕 T-SQL 查询 > 一书,不过适当的做了些编排和自己的理解。
 
让我们先来看看 Oracle 是怎么处理子查询的
CREATE TABLE Orders
(
  OrderID     VARCHAR2(6),
  CustomerID  VARCHAR2(6),
  EmployeeID  INT,
  OrderDate   DATE
);
TRUNCATE TABLE Orders;
INSERT INTO Orders VALUES('110001','WBQ',1,TO_DATE('2000-01-11','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110002','WBQ',1,TO_DATE('2000-01-21','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110003','WBQ',2,TO_DATE('2000-01-11','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110004','WBQ',3,TO_DATE('2000-02-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110005','CZH',1,TO_DATE('2000-02-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110006','CZH',2,TO_DATE('2000-03-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110007','CZH',2,TO_DATE('2000-03-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110008','KIDD',3,TO_DATE('2000-02-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110009','KIDD',1,TO_DATE('2000-04-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110010','KIDD',2,TO_DATE('2000-03-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110011','KIDD',3,TO_DATE('2000-02-01','YYYY-MM-DD'));
INSERT INTO Orders VALUES('110012','CZH',3,TO_DATE('2000-01-10','YYYY-MM-DD'));
COMMIT;
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders
  ORDER BY EmployeeID,OrderDate,OrderID 
 
 
-- 层递直至实现唯一为止
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders
  WHERE (EmployeeID,OrderDate,OrderID) IN
       (SELECT EmployeeID,OrderDate,MAX(OrderID)
          FROM Orders
         WHERE (EmployeeID,OrderDate) IN
               (SELECT EmployeeID,Max(OrderDate)
                  FROM Orders
                 GROUP BY EmployeeID)
         GROUP BY EmployeeID,OrderDate)
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID 
 
 
-- 多值,通常情况下该语句即可,不过在本例中 EmployeeID,OrderDate 并不唯一,导致结果非所需的
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders
  WHERE (EmployeeID,OrderDate) IN
       (SELECT EmployeeID,Max(OrderDate)
          FROM Orders
         GROUP BY EmployeeID)
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID 
 
 
--Error ,这是个错误的表达式
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders
  WHERE (EmployeeID,OrderDate,OrderID) IN
       (SELECT EmployeeID,MAX(OrderDate),MAX(OrderID)
          FROM Orders
         GROUP BY EmployeeID) 
 
 
-- 使用分析函数,也可以实现相应的子查询       
SELECT EmployeeID,OrderDate,OrderID,CustomerID FROM
(
  SELECT EmployeeID,OrderDate,OrderID,CustomerID,
         RANK() OVER (PARTITION BY EmployeeID ORDER BY OrderDate DESC,OrderID DESC) Rank
    FROM Orders
) a
  WHERE a.Rank=1
  
 
 
让我们继续看看 SQL Server 是如何处理的
CREATE TABLE Orders
(
  OrderID     VARCHAR(6),
  CustomerID  VARCHAR(6),
  EmployeeID  INT,
  OrderDate   DATETIME
);
INSERT INTO Orders VALUES('110001','WBQ',1,'2000-01-11');
INSERT INTO Orders VALUES('110002','WBQ',1,'2000-01-21');
INSERT INTO Orders VALUES('110003','WBQ',2,'2000-01-11');
INSERT INTO Orders VALUES('110004','WBQ',3,'2000-02-01');
INSERT INTO Orders VALUES('110005','CZH',1,'2000-02-01');
INSERT INTO Orders VALUES('110006','CZH',2,'2000-03-01');
INSERT INTO Orders VALUES('110007','CZH',2,'2000-03-01');
INSERT INTO Orders VALUES('110008','KIDD',3,'2000-02-01');
INSERT INTO Orders VALUES('110009','KIDD',1,'2000-04-01');
INSERT INTO Orders VALUES('110010','KIDD',2,'2000-03-01');
INSERT INTO Orders VALUES('110011','KIDD',3,'2000-02-01');
INSERT INTO Orders VALUES('110012','CZH',3,'2000-01-10');
COMMIT; 
 
 
-- 多值,通常情况下该语句即可,不过在本例中 EmployeeID,OrderDate 并不唯一,导致结果非所需的
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders O1
  WHERE rderDate=
       (SELECT MAX(OrderDate)
          FROM Orders O2
         WHERE O1.EmployeeID=O2.EmployeeID)
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID
等效于 Oracle 的以下语句
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders
  WHERE (EmployeeID,OrderDate) IN
       (SELECT EmployeeID,Max(OrderDate)
          FROM Orders
         GROUP BY EmployeeID)
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID 
 
 
正确的 SQLServer 子查询写法,用两个 MAX 求得唯一值
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders O1
  WHERE rderDate=
       (SELECT MAX(OrderDate)
          FROM Orders O2
         WHERE O1.EmployeeID=O2.EmployeeID)
   AND rderID=
        (SELECT Max(OrderID)
          FROM Orders O2
         WHERE O1.EmployeeID=O2.EmployeeID
           AND O1.OrderDate=O2.OrderDate)
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID 
 
 
-- 本例使用一种变通的方法,把几个应有的附加条件加进来然后返回,比较难以理解
SELECT
  CAST(SUBSTRING(BinStr,1,8) AS DATETIME) AS OrderDate,
  CAST(SUBSTRING(BinStr,9,6) AS VARCHAR) AS OrderID,
  CAST(SUBSTRING(BinStr,15,6) AS VARCHAR) AS CustomerID
FROM (SELECT EmployeeID,
             MAX(CAST(OrderDate AS BINARY(8))
                +CAST(OrderID AS BINARY(6))
                +CAST(CustomerID AS BINARY(6))) AS BinStr
        FROM Orders
       GROUP BY EmployeeID) D; 
 
 
-- 本例中在子查询中使用 TOP+Order 排序的方式获取相应的第一行值
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders O1
  WHERE rderID=
  (SELECT TOP(1) OrderID
     FROM Orders O2
    WHERE O1.EmployeeID=O2.EmployeeID
    ORDER BY OrderDate DESC,OrderID DESC,CustomerID
   )
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID 
 
 
-- 本例使用了 IN 子查询,可以自定义返回的 TOP N 条数
SELECT EmployeeID,OrderDate,OrderID,CustomerID
  FROM Orders O1
  WHERE OrderID IN
  (SELECT TOP(1) OrderID
     FROM Orders O2
    WHERE O1.EmployeeID=O2.EmployeeID
    ORDER BY OrderDate DESC,OrderID DESC,CustomerID
   )
  ORDER BY EmployeeID,OrderDate,OrderID,CustomerID 




本文转自baoqiangwang51CTO博客,原文链接:http://blog.51cto.com/baoqiangwang/310459 ,如需转载请自行联系原作者
相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
3月前
|
SQL 关系型数据库 MySQL
MySQL子查询篇(精选20道子查询练习题)-2
MySQL子查询篇(精选20道子查询练习题)
23 0
|
3月前
|
SQL 关系型数据库 MySQL
MySQL子查询篇(精选20道子查询练习题)-1
MySQL子查询篇(精选20道子查询练习题)
37 0
|
7月前
|
存储 数据库
MSSQL之五 连接查询与子查询
MSSQL之五 连接查询与子查询
49 0
|
9月前
|
SQL
SQL进阶之疯狂的子查询
今天我们不谈子查询的执行效率,只谈子查询功能。对于SQL语句来说,编程开发人员应该都不会陌生,其实各种复杂的逻辑最终落地也就是那么几个基本的招式,增删改查,然而我们经常听到武功招式中又各种连招,那就是了,子查询就是这么个意思。很多SQL简单查询完成不了的查询,子查询都可以很疯狂地完成。当然有的需要一个子查询就够了,有的甚至可能需要嵌套多个子查询来完成。
54 0
SQL进阶之疯狂的子查询
|
4月前
|
关系型数据库 MySQL Java
Mysql数据库 9.SQL语言 查询语句 连接查询、子查询
Mysql数据库 9.SQL语言 查询语句 连接查询、子查询
85 0
|
4月前
|
SQL 关系型数据库 MySQL
零基础带你学习MySQL—单行子查询和多行子查询(二十二)
零基础带你学习MySQL—单行子查询和多行子查询(二十二)
|
6月前
|
SQL 关系型数据库 MySQL
MySQL多表查询之子查询详解
在数据库查询中,多表查询是一项非常常见且重要的任务。它允许我们从多个相关联的表中检索和组合数据,以满足各种复杂的查询需求。在多表查询中,子查询是一种强大的工具,用于在查询中嵌套另一个查询。本文将深入探讨MySQL中的子查询,包括什么是子查询、如何编写子查询以及使用子查询解决的常见查询问题。
96 1
|
7月前
|
关系型数据库 MySQL
|
SQL Oracle 关系型数据库
MySQL多表查询,SQL,笛卡尔积等值连接自连接外连接,SQL99新特性,完整详细可收藏
MySQL多表查询,SQL,笛卡尔积等值连接自连接外连接,SQL99新特性,完整详细可收藏
322 0
MySQL多表查询,SQL,笛卡尔积等值连接自连接外连接,SQL99新特性,完整详细可收藏
|
SQL 数据库
SQL Sever 子查询与嵌套查询
作者主页:https://www.couragesteak.com/
SQL Sever 子查询与嵌套查询

热门文章

最新文章

相关课程

更多