T-SQL基础教程Day3
Posted SQL Server学习
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了T-SQL基础教程Day3相关的知识,希望对你有一定的参考价值。
第三章 联接
3.1交叉联接
交叉联接是最简单的联接类型。
交叉联接仅执行一个逻辑查询处理阶段——笛卡尔乘积
将一个输入表的每一行与另一个表的所有行匹配
SQL Server支持交叉联接的两种标准语法:
ANSI SQL-92和ANSI SQL-89语法,
建议使用ANSI SQL-92语法
3.1.1 ANSI SQL-92语法
SELECT C.custid, E.empid
FROM Sales.Customers AS C
CROSS JOIN HR.Employees AS E;
使用关键字CROSS JOIN
可以对表使用别名,如果未使用别名,需要使用完整的源表名称作为前缀。
3.1.2 ANSI SQL-89语法
SELECT C.custid, E.empid
FROM Sales.Customers AS C, HR.Employees AS E;
简单地在表名称之间制定一个逗号
两种语法之间没有逻辑或性能差异。
3.1.3 自交叉联接
可以联接同一个表的多个实例,此功能称为自联接,并且被所有基本联接类型支持(交叉联接、内部联接和外部联接)。
SELECT
E1.empid, E1.firstname, E1.lastname,
E2.empid, E2.firstname, E2.lastname
FROM HR.Employees AS E1
CROSS JOIN HR.Employees AS E2;
在自联接中,为表指定别名不是可选项。没有表别名,联接结果中的所有列名都将不明确。
3.1.4 生成数字表
交叉联接的一种用途是,生成一个整数数列结果集。
先创建一个名为Digits的表,其中包含名为digit的列,并且以数字0~9填充该表。
CREATE TABLE dbo.Digits(digit INT NOT NULL PRIMARY KEY);
INSERT INTO dbo.Digits(digit)
VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
SELECT digit FROM dbo.Digits;
SELECT D3.digit * 100 + D2.digit * 10 + D1.digit + 1 AS n
FROM dbo.Digits AS D1
CROSS JOIN dbo.Digits AS D2
CROSS JOIN dbo.Digits AS D3
ORDER BY n;
SQL Server 2022支持新语法:
SELECT * FROM GENERATE_SERIES(1, 1000);
3.2 内部联接
内部联接应用两个逻辑查询处理阶段——首先对作为交叉联接的两个输入表应用一个笛卡尔乘积,然后按指定的谓词筛选行。
也有两个标准语法:ANSI SQL-92和ANSI SQL-89
3.2.1 ANSI SQL-92语法
在表名称之间指定INNER JOIN关键字。
由于内部联接是默认联接,所以INNER关键字是可选的,可以仅指定JOIN关键字。指定的谓词用用于在名为ON的特定子句中筛选行,该谓词也称为联接条件。
SELECT E.empid, E.firstname, E.lastname, O.orderid
FROM HR.Employees AS E
INNER JOIN Sales.Orders AS O
ON E.empid = O.empid;
对大多数人来说,思考内部联接的最简单方式是,内部联接匹配每个雇员行到与其具有相同雇员ID的所有订单行,这是联接的一个简单思考方式。
联接的更正式思考方式是基于关系代数的,联接首先执行两个表的笛卡尔乘积,然后基于谓词E.empid = O.empid筛选行。
3.2.2 ANSI SQL-89语法
像交叉联接一样在表名称之间指定一个逗号,并在查询的WHERE子句中指定联接条件。
SELECT E.empid, E.firstname, E.lastname, O.orderid
FROM HR.Employees AS E, Sales.Orders AS O
WHERE E.empid = O.empid;
注意,ANSI SQL-89语法没有ON子句。
3.2.3 内部联接安全性
建议使用ANSI SQL-92联接语法,因为它在几个方面都是安全的。
假设打算写一个内部联接查询,并且失误忘记了指定联接条件。对于ANSI SQL-92语法,查询将无效,解析器会生成一个错误。
如果使用ANSI SQL-89语法时忘记指定联接条件,你会得到一个执行交叉联接的有效查询。因为查询不会失败,一段时间内可能不会注意到逻辑错误,你的应用程序哦用户可能最终使用了错误结果。对于简单的查询,程序员不太坑你会忘记指定联接条件,然而,多数生产查询更为复杂并具有多个表、筛选和其他查询元素,在这些情况下,忘记指定联接条件的可能性就增加了。
3.3.1 复合联接
复合联接是谓词涉及每侧多个属性的简单联接。
当需要联接两个基于主外键关系并且是复合关系(即基于多个属性)的表时,通常需要复合联接。
FROM dbo.Table1 AS T1
INNER JOIN dbo.Table2 AS T2
ON T1.col1 = T2.col1
AND T1.col2 = T2.col2
3.3.2 不等联接
当联接条件仅涉及等号运算时,称为相等联接。
当联接条件涉及除等号之外的任何运算符时,称为不等联接。
下面是一个不等联接的示例,此查询联接Employees表的两个实例,生成唯一的雇员对。
SELECT
E1.empid, E1.firstname, E1.lastname,
E2.empid, E2.firstname, E2.lastname
FROM HR.Employees AS E1
INNER JOIN HR.Employees AS E2
ON E1.empid < E2.empid;
3.3.3 多联接查询
当FROM子句中出现多个表运算符时,表运算符从左到右进行逻辑处理。也就是说,第一个表运算符的结果表将被视为第二个表运算符的左侧输入,第二个表运算符的结果将被视为第三个表运算符的左侧输入,以此类推。
SELECT
C.custid, C.companyname, O.orderid,
OD.productid, OD.qty
FROM Sales.Customers AS C
INNER JOIN Sales.Orders AS O
ON C.custid = O.custid
INNER JOIN Sales.OrderDetails AS OD
ON O.orderid = OD.orderid;
3.4.1 外部联接的基础知识
外部联接是在ANSI SQL-92中引入的,并且与内部联接和交叉联接不同,它只有一个标准语法——在表名之间制定一个JOIN关键字,并且在ON子句中指定联接条件。外部联接应用内部联接锁应用的两个逻辑处理阶段,再加上一个叫做“添加外部行”的第三个阶段,此阶段是此联接类型唯一具有的阶段。
在外部联接中,需要在表名之间使用关键字LEFT OUTER JOIN、RIGHT OUTER JOIN或FULL OUTER JOIN标记一个表为“保留表”。
OUTER关键字是可选的。LEFT关键字表示保留左侧表中的行,RIGHT表示保留右侧表中的行,FULL表示左侧和右侧表中的行都保留。
3.4.2 超越外部联接基础知识(可选内容)
1 包含缺失值
SELECT DATEADD(day, Nums.n - 1, CAST(\'20140101\' AS DATE)) AS orderdate,
O.orderid, O.custid, O.empid
FROM dbo.Nums
LEFT OUTER JOIN Sales.Orders AS O
ON DATEADD(day, Nums.n - 1, CAST(\'20140101\' AS DATE)) = O.orderdate
WHERE Nums.n <= DATEDIFF(day, \'20140101\', \'20161231\') + 1
ORDER BY orderdate;
2 从外部联接的非保留侧筛选属性
SELECT C.custid, C.companyname, O.orderid, O.orderdate
FROM Sales.Customers AS C
LEFT OUTER JOIN Sales.Orders AS O
ON C.custid = O.custid
WHERE O.orderdate >= \'20160101\';
3 在多联接查询中使用外部联接
4 在外部联接使用COUNT聚合
SELECT C.custid, COUNT(*) AS numorders
FROM Sales.Customers AS C
LEFT OUTER JOIN Sales.Orders AS O
ON C.custid = O.custid
GROUP BY C.custid;
章节代码
--------------------------------------------------------------------- -- Microsoft SQL Server 2012 T-SQL Fundamentals -- Chapter 03 - Joins -- ?Itzik Ben-Gan --------------------------------------------------------------------- --------------------------------------------------------------------- -- CROSS Joins --------------------------------------------------------------------- -- ANSI SQL-92 USE TSQL2012; SELECT C.custid, E.empid FROM Sales.Customers AS C CROSS JOIN HR.Employees AS E; -- ANSI SQL-89 SELECT C.custid, E.empid FROM Sales.Customers AS C, HR.Employees AS E; -- Self Cross-Join SELECT E1.empid, E1.firstname, E1.lastname, E2.empid, E2.firstname, E2.lastname FROM HR.Employees AS E1 CROSS JOIN HR.Employees AS E2; GO -- All numbers from 1 - 1000 -- Auxiliary table of digits USE TSQL2012; IF OBJECT_ID(\'dbo.Digits\', \'U\') IS NOT NULL DROP TABLE dbo.Digits; CREATE TABLE dbo.Digits(digit INT NOT NULL PRIMARY KEY); INSERT INTO dbo.Digits(digit) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); SELECT digit FROM dbo.Digits; GO -- All numbers from 1 - 1000 SELECT D3.digit * 100 + D2.digit * 10 + D1.digit + 1 AS n FROM dbo.Digits AS D1 CROSS JOIN dbo.Digits AS D2 CROSS JOIN dbo.Digits AS D3 ORDER BY n; --------------------------------------------------------------------- -- INNER Joins --------------------------------------------------------------------- -- ANSI SQL-92 USE TSQL2012; SELECT E.empid, E.firstname, E.lastname, O.orderid FROM HR.Employees AS E JOIN Sales.Orders AS O ON E.empid = O.empid; -- ANSI SQL-89 SELECT E.empid, E.firstname, E.lastname, O.orderid FROM HR.Employees AS E, Sales.Orders AS O WHERE E.empid = O.empid; GO -- Inner Join Safety /* SELECT E.empid, E.firstname, E.lastname, O.orderid FROM HR.Employees AS E JOIN Sales.Orders AS O; GO */ SELECT E.empid, E.firstname, E.lastname, O.orderid FROM HR.Employees AS E, Sales.Orders AS O; GO --------------------------------------------------------------------- -- Further Join Examples --------------------------------------------------------------------- --------------------------------------------------------------------- -- Composite Joins --------------------------------------------------------------------- -- Audit table for updates against OrderDetails USE TSQL2012; IF OBJECT_ID(\'Sales.OrderDetailsAudit\', \'U\') IS NOT NULL DROP TABLE Sales.OrderDetailsAudit; CREATE TABLE Sales.OrderDetailsAudit ( lsn INT NOT NULL IDENTITY, orderid INT NOT NULL, productid INT NOT NULL, dt DATETIME NOT NULL, loginname sysname NOT NULL, columnname sysname NOT NULL, oldval SQL_VARIANT, newval SQL_VARIANT, CONSTRAINT PK_OrderDetailsAudit PRIMARY KEY(lsn), CONSTRAINT FK_OrderDetailsAudit_OrderDetails FOREIGN KEY(orderid, productid) REFERENCES Sales.OrderDetails(orderid, productid) ); SELECT OD.orderid, OD.productid, OD.qty, ODA.dt, ODA.loginname, ODA.oldval, ODA.newval FROM Sales.OrderDetails AS OD JOIN Sales.OrderDetailsAudit AS ODA ON OD.orderid = ODA.orderid AND OD.productid = ODA.productid WHERE ODA.columnname = N\'qty\'; --------------------------------------------------------------------- -- Non-Equi Joins --------------------------------------------------------------------- -- Unique pairs of employees SELECT E1.empid, E1.firstname, E1.lastname, E2.empid, E2.firstname, E2.lastname FROM HR.Employees AS E1 JOIN HR.Employees AS E2 ON E1.empid < E2.empid; --------------------------------------------------------------------- -- Multi-Join Queries --------------------------------------------------------------------- SELECT C.custid, C.companyname, O.orderid, OD.productid, OD.qty FROM Sales.Customers AS C JOIN Sales.Orders AS O ON C.custid = O.custid JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid; --------------------------------------------------------------------- -- Fundamentals of Outer Joins --------------------------------------------------------------------- -- Customers and their orders, including customers with no orders SELECT C.custid, C.companyname, O.orderid FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid; -- Customers with no orders SELECT C.custid, C.companyname FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid WHERE O.orderid IS NULL; GO --------------------------------------------------------------------- -- Beyond the Fundamentals of Outer Joins --------------------------------------------------------------------- --------------------------------------------------------------------- -- Including Missing Values --------------------------------------------------------------------- SELECT DATEADD(day, n-1, \'20060101\') AS orderdate FROM dbo.Nums WHERE n <= DATEDIFF(day, \'20060101\', \'20081231\') + 1 ORDER BY orderdate; SELECT DATEADD(day, Nums.n - 1, \'20060101\') AS orderdate, O.orderid, O.custid, O.empid FROM dbo.Nums LEFT OUTER JOIN Sales.Orders AS O ON DATEADD(day, Nums.n - 1, \'20060101\') = O.orderdate WHERE Nums.n <= DATEDIFF(day, \'20060101\', \'20081231\') + 1 ORDER BY orderdate; --------------------------------------------------------------------- -- Filtering Attributes from Non-Preserved Side of Outer Join --------------------------------------------------------------------- SELECT C.custid, C.companyname, O.orderid, O.orderdate FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid WHERE O.orderdate >= \'20070101\'; --------------------------------------------------------------------- -- Using Outer Joins in a Multi-Join Query --------------------------------------------------------------------- SELECT C.custid, O.orderid, OD.productid, OD.qty FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid; -- Option 1: use outer join all along SELECT C.custid, O.orderid, OD.productid, OD.qty FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid LEFT OUTER JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid; -- Option 2: change join order SELECT C.custid, O.orderid, OD.productid, OD.qty FROM Sales.Orders AS O JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid RIGHT OUTER JOIN Sales.Customers AS C ON O.custid = C.custid; -- Option 3: use parentheses SELECT C.custid, O.orderid, OD.productid, OD.qty FROM Sales.Customers AS C LEFT OUTER JOIN (Sales.Orders AS O JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid) ON C.custid = O.custid; --------------------------------------------------------------------- -- Using the COUNT Aggregate with Outer Joins --------------------------------------------------------------------- SELECT C.custid, COUNT(*) AS numorders FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid GROUP BY C.custid; SELECT C.custid, COUNT(O.orderid) AS numorders FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid GROUP BY C.custid;
练习代码
--------------------------------------------------------------------- -- Microsoft SQL Server 2012 T-SQL Fundamentals -- Chapter 03 - Joins -- Solutions -- ?Itzik Ben-Gan --------------------------------------------------------------------- -- 1 -- 1-1 -- Write a query that generates 5 copies out of each employee row -- Tables involved: TSQL2012 database, Employees and Nums tables --Desired output empid firstname lastname n ----------- ---------- -------------------- ----------- 1 Sara Davis 1 2 Don Funk 1 3 Judy Lew 1 4 Yael Peled 1 5 Sven Buck 1 6 Paul Suurs 1 7 Russell King 1 8 Maria Cameron 1 9 Zoya Dolgopyatova 1 1 Sara Davis 2 2 Don Funk 2 3 Judy Lew 2 4 Yael Peled 2 5 Sven Buck 2 6 Paul Suurs 2 7 Russell King 2 8 Maria Cameron 2 9 Zoya Dolgopyatova 2 1 Sara Davis 3 2 Don Funk 3 3 Judy Lew 3 4 Yael Peled 3 5 Sven Buck 3 6 Paul Suurs 3 7 Russell King 3 8 Maria Cameron 3 9 Zoya Dolgopyatova 3 1 Sara Davis 4 2 Don Funk 4 3 Judy Lew 4 4 Yael Peled 4 5 Sven Buck 4 6 Paul Suurs 4 7 Russell King 4 8 Maria Cameron 4 9 Zoya Dolgopyatova 4 1 Sara Davis 5 2 Don Funk 5 3 Judy Lew 5 4 Yael Peled 5 5 Sven Buck 5 6 Paul Suurs 5 7 Russell King 5 8 Maria Cameron 5 9 Zoya Dolgopyatova 5 (45 row(s) affected) -- Solution SELECT E.empid, E.firstname, E.lastname, N.n FROM HR.Employees AS E CROSS JOIN dbo.Nums AS N WHERE N.n <= 5 ORDER BY n, empid; -- 1-2 (Optional, Advanced) -- Write a query that returns a row for each employee and day -- in the range June 12, 2009 ?June 16 2009. -- Tables involved: TSQL2012 database, Employees and Nums tables --Desired output empid dt ----------- ----------------------- 1 2009-06-12 00:00:00.000 1 2009-06-13 00:00:00.000 1 2009-06-14 00:00:00.000 1 2009-06-15 00:00:00.000 1 2009-06-16 00:00:00.000 2 2009-06-12 00:00:00.000 2 2009-06-13 00:00:00.000 2 2009-06-14 00:00:00.000 2 2009-06-15 00:00:00.000 2 2009-06-16 00:00:00.000 3 2009-06-12 00:00:00.000 3 2009-06-13 00:00:00.000 3 2009-06-14 00:00:00.000 3 2009-06-15 00:00:00.000 3 2009-06-16 00:00:00.000 4 2009-06-12 00:00:00.000 4 2009-06-13 00:00:00.000 4 2009-06-14 00:00:00.000 4 2009-06-15 00:00:00.000 4 2009-06-16 00:00:00.000 5 2009-06-12 00:00:00.000 5 2009-06-13 00:00:00.000 5 2009-06-14 00:00:00.000 5 2009-06-15 00:00:00.000 5 2009-06-16 00:00:00.000 6 2009-06-12 00:00:00.000 6 2009-06-13 00:00:00.000 6 2009-06-14 00:00:00.000 6 2009-06-15 00:00:00.000 6 2009-06-16 00:00:00.000 7 2009-06-12 00:00:00.000 7 2009-06-13 00:00:00.000 7 2009-06-14 00:00:00.000 7 2009-06-15 00:00:00.000 7 2009-06-16 00:00:00.000 8 2009-06-12 00:00:00.000 8 2009-06-13 00:00:00.000 8 2009-06-14 00:00:00.000 8 2009-06-15 00:00:00.000 8 2009-06-16 00:00:00.000 9 2009-06-12 00:00:00.000 9 2009-06-13 00:00:00.000 9 2009-06-14 00:00:00.000 9 2009-06-15 00:00:00.000 9 2009-06-16 00:00:00.000 (45 row(s) affected) -- Solution SELECT E.empid, DATEADD(day, D.n - 1, \'20090612\') AS dt FROM HR.Employees AS E CROSS JOIN Nums AS D WHERE D.n <= DATEDIFF(day, \'20090612\', \'20090616\') + 1 ORDER BY empid, dt; -- 2 -- Return US customers, and for each customer the total number of orders -- and total quantities. -- Tables involved: TSQL2012 database, Customers, Orders and OrderDetails tables --Desired output custid numorders totalqty ----------- ----------- ----------- 32 11 345 36 5 122 43 2 20 45 4 181 48 8 134 55 10 603 65 18 1383 71 31 4958 75 9 327 77 4 46 78 3 59 82 3 89 89 14 1063 (13 row(s) affected) -- Solution SELECT C.custid, COUNT(DISTINCT O.orderid) AS numorders, SUM(OD.qty) AS totalqty FROM Sales.Customers AS C JOIN Sales.Orders AS O ON O.custid = C.custid JOIN Sales.OrderDetails AS OD ON OD.orderid = O.orderid WHERE C.country = N\'USA\' GROUP BY C.custid; -- 3 -- Return customers and their orders including customers who placed no orders -- Tables involved: TSQL2012 database, Customers and Orders tables -- Desired output custid companyname orderid orderdate ----------- --------------- ----------- ------------------------ 85 Customer ENQZT 10248 2006-07-04 00:00:00.000 79 Customer FAPSM 10249 2006-07-05 00:00:00.000 34 Customer IBVRG 10250 2006-07-08 00:00:00.000 84 Customer NRCSK 10251 2006-07-08 00:00:00.000 ... 73 Customer JMIKW 11074 2008-05-06 00:00:00.000 68 Customer CCKOT 11075 2008-05-06 00:00:00.000 9 Customer RTXGC 11076 2008-05-06 00:00:00.000 65 Customer NYUHS 11077 2008-05-06 00:00:00.000 22 Customer DTDMN NULL NULL 57 Customer WVAXS NULL NULL (832 row(s) affected) -- Solution SELECT C.custid, C.companyname, O.orderid, O.orderdate FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON O.custid = C.custid; -- 4 -- Return customers who placed no orders -- Tables involved: TSQL2012 database, Customers and Orders tables -- Desired output custid companyname ----------- --------------- 22 Customer DTDMN 57 Customer WVAXS (2 row(s) affected) -- Solution SELECT C.custid, C.companyname FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON O.custid = C.custid WHERE O.orderid IS NULL; -- 5 -- Return customers with orders placed on Feb 12, 2007 along with their orders -- Tables involved: TSQL2012 database, Customers and Orders tables -- Desired output custid companyname orderid orderdate ----------- --------------- ----------- ----------------------- 66 Customer LHANT 10443 2007-02-12 00:00:00.000 5 Customer HGVLZ 10444 2007-02-12 00:00:00.000 (2 row(s) affected) -- Solution SELECT C.custid, C.companyname, O.orderid, O.orderdate FROM Sales.Customers AS C JOIN Sales.Orders AS O ON O.custid = C.custid WHERE O.orderdate = \'20070212\'; -- 6 (Optional, Advanced) -- Return customers with orders placed on Feb 12, 2007 along with their orders -- Also return customers who didn\'t place orders on Feb 12, 2007 -- Tables involved: TSQL2012 database, Customers and Orders tables -- Desired output custid companyname orderid orderdate ----------- --------------- ----------- ----------------------- 72 Customer AHPOP NULL NULL 58 Customer AHXHT NULL NULL 25 Customer AZJED NULL NULL 18 Customer BSVAR NULL NULL 91 Customer CCFIZ NULL NULL ... 33 Customer FVXPQ NULL NULL 53 Customer GCJSG NULL NULL 39 Customer GLLAG NULL NULL 16 Customer GYBBY NULL NULL 4 Customer HFBZG NULL NULL 5 Customer HGVLZ 10444 2007-02-12 00:00:00.000 42 Customer IAIJK NULL NULL 34 Customer IBVRG NULL NULL 63 Customer IRRVL NULL NULL 73 Customer JMIKW NULL NULL 15 Customer JUWXK NULL NULL ... 21 Customer KIDPX NULL NULL 30 Customer KSLQF NULL NULL 55 Customer KZQZT NULL NULL 71 Customer LCOUJ NULL NULL 77 Customer LCYBZ NULL NULL 66 Customer LHANT 10443 2007-02-12 00:00:00.000 38 Customer LJUCA NULL NULL 59 Customer LOLJO NULL NULL 36 Customer LVJSO NULL NULL 64 Customer LWGMD NULL NULL 29 Customer MDLWA NULL NULL ... (91 row(s) affected) -- Solution SELECT C.custid, C.companyname, O.orderid, O.orderdate FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON O.custid = C.custid AND O.orderdate = \'20070212\'; -- 7 (Optional, Advanced) -- Return all customers, and for each return a Yes/No value -- depending on whether the customer placed an order on Feb 12, 2007 -- Tables involved: TSQL2012 database, Customers and Orders tables -- Desired output custid companyname HasOrderOn20070212 ----------- --------------- ------------------ 1 Customer NRZBB No 2 Customer MLTDN No 3 Customer KBUDE No 4 Customer HFBZG No 5 Customer HGVLZ Yes 6 Customer XHXJV No 7 Customer QXVLA No 8 Customer QUHWH No 9 Customer RTXGC No 10 Customer EEALV No ... (91 row(s) affected) -- Solution SELECT DISTINCT C.custid, C.companyname, CASE WHEN O.orderid IS NOT NULL THEN \'Yes\' ELSE \'No\' END AS [HasOrderOn20070212] FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON O.custid = C.custid AND O.orderdate = \'20070212\';
JAVA入门零基础小白教程day06-类和对象
4day06-JAVAOOP
课程目标
1. 【理解】 什么是面向对象
2. 【理解】 类和对象的关系
3. 【掌握】 类的定义和使用
4. 【掌握】 三大特征之封装
5. 【掌握】 this关键字的使用
一.面向对象概述
1.1什么是面向对象
Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下, 使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算 机事件的设计思想。 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。
1.2面向过程与面向对象
面向过程
完成一个功能时,功能的每一个步骤,都需要我们进行参与,每一个细节都需要了解清楚,才能完成。强调的是过程。
面向对象
强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去 操作实现
举例
1.3三大特征
封装 继承 多态
层层递进 互为前提
1.4小结
做事情 首先第一想到的是对象,那个对象能帮我们做事情
有对象: 直接用
没有对象: 我们自己造对象在进行使用
二.类和对象
2.1什么是类
类是一组相关属性和行为的集合。类就是现实生活的一个事物(java语言就是对于现实生活的描述),事物由属性和行为组成。
【类就是描述现实生活中的某一个事物,这个事物是由属性和行为组成】
2.2什么是对象
对象:是一类事物的具体体现。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性和行为
2.3类与对象的关系
类是对一类事物的描述,是抽象的
对象是一类事物的实例,是具体的
类是对象的模板,对象是类的实体
类:学生 汽车图纸
对象: 班长,一个具体的对象 大众 宝马 MG
三.类的定义和使用
3.1类的定义
3.1.1语法格式
public class 类名
//成员变量 --属性
//成员方法 --行为
3.1.2定义学生类
public class Student //成员变量
String name;//姓名
int age;//年龄
// 成员方法
// 学习的方法
public void study()
System.out.println("好好学习,天天向上");
//吃饭的方法
public void eat()
System.out.println("学习饿了要吃饭");
3.2对象的使用
3.2.1创建对象格式
类名 对象名 = new 类名();
3.2.2访问类中的成员
对象名.成员变量;
对象名.成员方法();
代码演示
public class Test01_Student
public static void main(String[] args)
//创建对象格式:类名 对象名 = new 类名();
Student s = new Student();
System.out.println("s:"+s); //
//直接输出成员变量值
System.out.println("姓名:"+s.name); //null
System.out.println("年龄:"+s.age); //0
System.out.println("‐‐‐‐‐‐‐‐‐‐");
//给成员变量赋值
s.name = "赵丽颖";
s.age = 18;
//再次输出成员变量的值
System.out.println("姓名:"+s.name); //赵丽颖
System.out.println("年龄:"+s.age); //18
System.out.println("‐‐‐‐‐‐‐‐‐‐");
//调用成员方法
s.study(); // "好好学习,天天向上"
s.eat(); // "学习饿了要吃饭"
3.3成员变量的默认值
3.4类与对象的练习
-
定义手机类
public class Phone // 成员变量 String brand; //品牌 int price; //价格 String color; //颜色 // 成员方法 //打电话 public void call(String name) System.out.println("给"+name+"打电话"); //发短信 public void sendMessage() System.out.println("群发短信");
-
测试类
public class Test02Phone public static void main(String[] args) //创建对象 Phone p = new Phone(); //输出成员变量值 System.out.println("品牌:"+p.brand);//null System.out.println("价格:"+p.price);//0 System.out.println("颜色:"+p.color);//null System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐"); //给成员变量赋值 p.brand = "锤子"; p.price = 2999; p.color = "棕色"; //再次输出成员变量值 System.out.println("品牌:"+p.brand);//锤子 System.out.println("价格:"+p.price);//2999 System.out.println("颜色:"+p.color); //棕色 System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐"); //调用成员方法 p.call("紫霞"); p.sendMessage();
四.成员变量和局部变量的区别
五.封装
5.1什么是封装
面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。 封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。
5.2封装的引入
/*
定义一个学生类:
成员变量:name,age
成员方法:show()方法
private:私有的。可以修饰成员变量和成员方法。
注意:被private修饰的成员只能在本类中访问。
其实我讲到现在讲解的是一个封装的思想。
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
*/
public class Student
//姓名
String name;
//年龄
private int age;
/**
* 为了年龄的正确性,写一个方法给年龄进行赋值
* 两个明确: 1、需要一个int类型的参数
* 2、需要不需要返回值类型
* @param a
*/
public void setAge(int a)
if( a <=0 || a >= 100)
System.out.println("您给出的年龄有问题!!");
else
age = a;
public void show()
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
public class StudentDemo
public static void main(String[] args)
//创建对象
Student s = new Student();
s.show();
System.out.println("=========================");
//给成员变量赋值
s.name = "小江";
// s.age = 27;
s.show();
System.out.println("=========================");
s.name = "小燕";
//这次给成员变量赋值一个 负数
// s.age = -27;
//年龄给一个负数不合理,那如何是好呢?
//解决办法:不让用户直接赋值(private),然后方法(setAge())进行判断
s.setAge(27);
s.show();
5.3封装的原则
将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。
5.3.1如何封装
5.3.2private 关键字
-
什么是private关键字
1. private是一个权限修饰符,代表最小权限。 2. 可以修饰成员变量和成员方法。 3. 被private修饰后的成员变量和成员方法,只在本类中才能访问
-
private的使用格式
private 数据类型 变量名 ;
-
使用 private 修饰成员变量,代码如下
public class Student //private修饰成员变量 private int num = 10; public void show() //private 只能在本类中使用 System.out.println(num); //private修饰成员 private void method() System.out.println("我是method"); public void function() //private 只能在本类中使用 method();
public class StudentTest
public static void main(String[] args)
Student s = new Student();
//不能访问私有的成员变量
// System.out.println(s.num);
s.show();
//不能访问私有的成员方法
// s.method();
s.function();
-
提供
getXxx
方法 /setXxx
方法,可以访问成员变量,代码如下public class Student //姓名 private String name; //年龄 private int age; //姓名获取值 public String getName() return name; //姓名设置值 public void setName(String n) name = n; //年龄获取值 public int getAge() return age; //年龄设置值 public void setAge(int a) age = a;
public class StudentDemo
public static void main(String[] args)
//创建对象
Student s = new Student();
//使用成员变量
//错误: 私有的成员变量是不能被访问的
// System.out.println(s.name);
// System.out.println(s.age);
//通过方法访问成员变量
System.out.println(s.getName()+" : "+s.getAge());
//给成员变量赋值
s.setName("一燕");
s.setAge(18);
System.out.println(s.getName()+" : "+s.getAge());
5.3.3 this 关键字
-
问题描述
我们发现 setXxx 方法中的形参名字并不符合见名知意的规定,那么如果修改与成员变量名一致,是否就见名知意 了呢?代码如下:
public class Student private String name; private int age; public void setName(String name) name = name; public void setAge(int age) age = age;
经过修改和测试,我们发现新的问题,成员变量赋值失败了。也就是说,在修改了 setXxx() 的形参变量名后,方法并没有给成员变量赋值!这是由于形参变量名与成员变量名重名,导致成员变量名被隐藏,方法中的变量名,无 法访问到成员变量,从而赋值失败。所以,我们只能使用this关键字,来解决这个重名问题。
-
this
的含义this代表所在类的当前对象的引用(地址值),即对象自己的引用。
-
this
的使用格式this.成员变量名;
-
代码修改
public class Student private String name; private int age; public void setName(String name) //name = name; this.name = name; public String getName() return name;//其实这里隐含this public void setAge(int age) //age = age; this.age = age; public int getAge() return age;
六.构造方法
6.1构造方法概述
构造方法: 用于对象数据初始化
小贴士:无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,
一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。
6.2构造方法的定义格式
/*
构造方法名与类名相同
没有返回值类型,连void
没有具体的返回值
*/
修饰符 构造方法名(参数列表)
// 方法体
6.3构造方法的使用
构造方法的写法上,方法名与它所在的类名相同。它没有返回值,所以不需要返回值类型,甚至不需要void。使用
构造方法后,代码如下
public class Student
private String name;
private int age;
// 无参数构造方法
public Student()
System.out.println("我是无参构造方法");
// 有参数构造方法
public Student(String name,int age)
this.name = name;
this.age = age;
public class StudentDemo
public static void main(String[] args)
//无参构造
Student s = new Student();
System.out.println(s);
//有参构造
Student s1 = new Student("小燕",27);
System.out.println(s1.getName());
System.out.println(s1.getAge());
6.3构造方法重载
// 构造方法是可以重载的
public class Student
public Student()
public Student(String name, int age)
this.name = name;
this.age = age;
public Student(String name)
this.name = name;
public Student(int age)
this.age = age;
6.4构造方法的注意事项
1. 如果你不提供构造方法,系统会给出无参数构造方法。√
2. 如果你提供了构造方法,系统将不再提供无参数构造方法。
3. 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
需求: 现在类是可以创建对象,但是有些情况下不让别人创建对象,请问怎么办?
构造方法私有
标准JavaBean编写
JavaBean 是 Java语言编写类的一种标准规范。
符合 JavaBean 的类,有构造方法 , 提供操作属性的set get方法
public class ClassName
//成员变量
//构造方法
//无参构造方法【必须】
//有参构造方法【建议】
//成员方法
//getXxx()
//setXxx()
编写Student类
public class Student
//成员变量
private String name;
private int age;
//构造方法
public Student()
public Student(String name,int age)
this.name = name;
this.age = age;
//成员方法
publicvoid setName(String name)
this.name = name;
public String getName()
return name;
publicvoid setAge(int age)
this.age = age;
publicint getAge()
return age;
测试
public class TestStudent
public static void main(String[] args)
//无参构造使用
Student s= new Student();
s.setName("柳岩");
s.setAge(18);
System.out.println(s.以上是关于T-SQL基础教程Day3的主要内容,如果未能解决你的问题,请参考以下文章