笔记——《SQL从入门到提高》
本笔记整理了杨中科老师在传智播客.Net培训的《SQL从入门到提高》视频讲座。
数据库相关概念
1、什么是索引?优缺点是什么?
索引是对数据库表中一列或多列的值进行排序的一种单独的、物理的数据库结构。
优点:
1) 大大加快数据的检索速度;
2) 创建唯一性索引,保证数据库表中每一行数据的唯一性;
3) 加速表和表之间的连接;
4) 在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
缺点:
1) 索引需要占物理空间;
2) 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
优点:
1) 大大加快数据的检索速度;
2) 创建唯一性索引,保证数据库表中每一行数据的唯一性;
3) 加速表和表之间的连接;
4) 在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
缺点:
1) 索引需要占物理空间;
2) 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
2、业务主键和逻辑主键
业务主键是使用有业务意义的字段做主键,比如身份证号,银行账号等;
逻辑主键是使用没有任何业务意义的字段做主键。因为很难保证业务主键不会重复(身份证号重复)、不会变化(账号升位),因此推荐使用逻辑主键。
SQL Server 的使用
1、SQL Server 两种常用的主键数据类型
1) int(或 bigint) + 标识列(又称自动增长字段)
用标识列实现字段自增可以避免并发等问题,不要开发人员控制自增。用标识列的字段在Insert的时候不用指定主键的值。
优点:占用空间小、无需开发人员干预、易读;
缺点:效率低,数据导入导出的时候很痛苦。
设置:“修改表”->选定主键->“列属性”->“标识规范”选择“是”
用标识列实现字段自增可以避免并发等问题,不要开发人员控制自增。用标识列的字段在Insert的时候不用指定主键的值。
优点:占用空间小、无需开发人员干预、易读;
缺点:效率低,数据导入导出的时候很痛苦。
设置:“修改表”->选定主键->“列属性”->“标识规范”选择“是”
2) uniqueidentifier(又称GUID、UUID)
GUID算法是一种可以产生唯一表示的高效算法,它使用网卡MAC、地址、纳秒级时 间、芯片ID码等算出来的,这样保证每次生成的GUID永远不会重复,无论是同一计算机还是不同计算机。在公元3400年前产生的GUID与任何其他产生过的GUID都不相同。SQL Server中生成GUID的函数newid()。
优点:效率高、数据导入导出方便;
缺点:占用空间大、不易读。
GUID算法是一种可以产生唯一表示的高效算法,它使用网卡MAC、地址、纳秒级时 间、芯片ID码等算出来的,这样保证每次生成的GUID永远不会重复,无论是同一计算机还是不同计算机。在公元3400年前产生的GUID与任何其他产生过的GUID都不相同。SQL Server中生成GUID的函数newid()。
优点:效率高、数据导入导出方便;
缺点:占用空间大、不易读。
业界主流倾向于使用GUID。
SQL 基础
1、DDL(数据定义语言)
1) 创建数据表:
--创建表,SQL Server 的数据类型. CREATE TABLE T_Person( Id int NOT NULL , Name nvarchar(50), Age int NULL , PRIMARY KEY (Id)); --创建表,添加外键. CREATE TABLE T_Users( StudentNo CHAR (4), CourseNo CHAR (4), Score INT , PRIMARY KEY (StudentNo), FOREIGN KEY (CourseNo) REFERENCES T_Course(CourseNo)); |
2) 修改表结构:
--修改表结构,添加字段 ALTER TABLE T_Person ADD NickName nvarchar(50) NULL ; --修改表结构,删除字段 ALTER TABLE T_Person DROP NickName; |
3) 删除数据表:
DROP TABLE T_Person; |
4) 创建索引:
CREATE [ UNIQUE ] INDEX <索引名> ON <基本表名>(<列名序列>); |
2、DML(数据操纵语言)
1) 插入语句:
INSERT INTO T_Person(Id, Name , Age) VALUES (1, 'Jim' , 20); |
2) 更新语句:
UPDATE T_Person SET Age=Age+1 where Name = 'tom' or Age<25; |
3) 删除语句:
--删除表中所有记录. DELETE FROM T_Person; --删除表中指定记录. DELETE FROM T_Person WHERE Age>20; |
4) 查询语句:
--简单的数据查询. SELECT * FROM T_Employee; --只查询需要的列. SELECT FNumber FROM T_Employee; --给列取别名. SELECT FNumber AS 编号, FName AS 姓名 FROM T_Employee; --使用 WHERE 查询符合条件的记录. SELECT FName FROM T_Employee WHERE FSalary<5000; --对表记录进行排序. SELECT * FROM T_Employee ORDER BY FAge ASC ,FSalary DESC ; --ORDER BY 子句要放在 WHERE 子句之后. SELECT * FROM T_Employee WHERE FAge>23 ORDER BY FAge DESC ,FSalary DESC ; --WHERE 中可以使用的逻辑运算符:or、and、not、<、>、=、>=、<=、!=、<>等. --查询不与任何表关联的数据. SELECT 1+1; SELECT newid(); SELECT getdate(); --模糊匹配,首字母未知. SELECT * FROM T_Employee WHERE FName LIKE '_arry' ; --模糊匹配,前后多个字符未知. SELECT * FROM T_Employee WHERE FName LIKE '%n%' ; --NULL 表示“不知道”,有 NULL 参与的运算结果一般都为 NULL. --查询数据是否为 NULL,不能用 = 、!= 或 <>. SELECT * FROM T_Employee WHERE FName IS NULL ; SELECT * FROM T_Employee WHERE FName IS NOT NULL ; --查询在某个范围内的数据,IN 表示包含于. SELECT * FROM T_Employee WHERE FAge IN (23, 25, 28); --下面两句等价。 SELECT * FROM T_Employee WHERE FAge>=23 AND FAge<=30; SELECT * FROM T_Employee WHERE FAge BETWEEN 23 AND 30; |
数据分组
--下面语句操作顺序:先按年龄相同的进行分组,然后显式每组年龄,并统计出每组行数. --注意:聚合函数是对分组操作结果进行运算. SELECT FAge, COUNT (*) FROM T_Employee GROUP BY FAge; --下面语句错误,因为一组中各行姓名 FName 是不同的, --不能使用没有在 GROUP BY 中出现的字段,聚合函数除外. SELECT FAge,FName, COUNT (*) FROM T_Employee GROUP BY FAge; --可以像下面这样写,因为一组中最大工资只有一个. SELECT FAge, MAX (FSalary), COUNT (*) FROM T_Employee GROUP BY FAge; --GROUP BY 应该放在 WHERE 的后面,聚合函数是不能出现在 WHERE 语句中的, --WHERE 是对原始表记录进行条件操作,ORDER BY 是在条件操作之后进行分组操作, --HAVING 放在 ORDER BY 后面,用来对分组操作的结果集进行筛选操作, --HAVING 是 ORDER BY 的子句,不能代替 WHERE,HAVING 中的字段必须出现在 GROUP BY 中. --下面语句操作顺序:先按年龄相同的进行分组,然后筛选出行数大于 1 的分组。 SELECT FAge, COUNT (*) FROM T_Employee GROUP BY FAge HAVING COUNT (*)>1; --下面语句是错误的,因为 FSalary 在每个分组中不是唯一的,不能用来标识分组. --HAVING能用的列和 SELECT 中能用的列是一样的。 SELECT FAge, COUNT (*) FROM T_Employee GROUP BY FAge HAVING FSalary>2000; |
限制结果集
--限制结果集的行数: SELECT TOP 5 * FROM T_Employee ORDER BY FSalary DESC ; --下面语句意图:按照工资从高到低排序,检索从第六名开始一共三个人的信息。 --操作顺序:从内层到外层 --先查询倒序前五名的编号,然后排除前五名编号, --得到的数据从第六名开始,最后按倒序从第六名开始取前三名。 SELECT TOP 3 * FROM T_Employee WHERE FNumber NOT IN ( SELECT TOP 5 FNumber FROM T_Employee ORDER BY FSalary DESC ) ORDER BY FSalary DESC ; --去除重复数据,所去除的是完全重复的记录,即所有字段都相同者去掉。 --查询所有员工的部门信息,部门信息重复. SELECT FDepartment FROM T_Employee; --想要查询公司包含多少个部门,结果集中部门信息重复,加关键字 DISTINCT 可以消除重复。 SELECT DISTINCT FDepartment FROM T_Employee; |
联合结果集
--把 UNION 前后的查询结果集合为一个结果集,返回的结果字段数必须相同,各字段类型必须相容。 --默认情况下联合结果集会自动去除重复。如果不想去除重复数据,需要在 UNION 后加上 ALL。 SELECT FName,FAge, '临时工,无部门' FROM T_TempEmployee UNION SELECT FName,FAge,FDepartment FROM T_Employee; --不去除重复的联合结果集. SELECT FName,FAge, '临时工,无部门' FROM T_TempEmployee UNION ALL SELECT FName,FAge,FDepartment FROM T_Employee; --使用联合结果集做报表. SELECT '正式员工最高年龄' , MAX (FAge) FROM T_Employee UNION ALL SELECT '正式员工最低年龄' , MIN (FAge) FROM T_Employee UNION ALL SELECT '临时工最高年龄' , MAX (FAge) FROM T_TempEmployee UNION ALL SELECT '临时工最低年龄' , MIN (FAge) FROM T_TempEmployee; --使用联合结果集查询所用员工工资合计. SELECT FNumber, FSalary FROM T_Employee UNION SELECT '工资合计' , SUM (FSalary) FROM T_Employee; |
SQL Server 部分函数
1、数学函数
ABS():求绝对值
CEILING():舍入到最大整数(上限)。CEILING(3.33)=4,CEILING(-3.33)=-3
FLOOR():舍入到最小整数(下限)。FLOOR(3.33)=3,FLOOR(-3.33)=-4
ROUND():四舍五入。舍入到“离我半径最近的数”。ROUND(3.1415,3)=3.142
CEILING():舍入到最大整数(上限)。CEILING(3.33)=4,CEILING(-3.33)=-3
FLOOR():舍入到最小整数(下限)。FLOOR(3.33)=3,FLOOR(-3.33)=-4
ROUND():四舍五入。舍入到“离我半径最近的数”。ROUND(3.1415,3)=3.142
2、字符串函数
LEN():求字符串长度。LEN('abc')=3
LOWER()、UPPER():转小写、大写
LTRIM():去掉字符串左侧空格
RTRIM():去掉字符串右侧空格
SUBSTRING(string,start_position,length):取子串,参数 string 为主字符串,start_position 为子字符串在主字符串中的起始位置,length 为子字符串的最大长度。
LOWER()、UPPER():转小写、大写
LTRIM():去掉字符串左侧空格
RTRIM():去掉字符串右侧空格
SUBSTRING(string,start_position,length):取子串,参数 string 为主字符串,start_position 为子字符串在主字符串中的起始位置,length 为子字符串的最大长度。
3、日期函数
GETDATE():取当前日期时间
DATEADD(datepart,number,date):计算增加以后的日期。参数 date 为待计算的日期,参数 datepart 为计量单位(YEAR,YY,MONTH,MM,DAY,DD 等)DATEADD(DAY,3,date)为计算日期 date 的 3 天后的日期,DATEADD(MONTH,-8,date)为计算日期 date 的 8 个月前的日期
DATEDIFF(datepart,startdate,enddate):计算两个日期之间的差额。datepart 为计量单位
DATEPART(datepart,date):返回一个日期的特定的部分
DATEADD(datepart,number,date):计算增加以后的日期。参数 date 为待计算的日期,参数 datepart 为计量单位(YEAR,YY,MONTH,MM,DAY,DD 等)DATEADD(DAY,3,date)为计算日期 date 的 3 天后的日期,DATEADD(MONTH,-8,date)为计算日期 date 的 8 个月前的日期
DATEDIFF(datepart,startdate,enddate):计算两个日期之间的差额。datepart 为计量单位
DATEPART(datepart,date):返回一个日期的特定的部分
--查询员工入职年数. SELECT FName,FInDate,DATEDIFF( YEAR ,FInDate,GETDATE()) FROM T_Employee; --查询各入职年数的员工个数. SELECT DATEDIFF( YEAR ,FInDate,GETDATE()), COUNT (*) FROM T_Employee GROUP BY DATEDIFF( YEAR ,FInDate,GETDATE()); |
4、类型转换函数
CAST(expression AS date_type)
CONVERT(date_type,expression)
CONVERT(date_type,expression)
--字符串转换为整数 SELECT CAST ( '123' AS INTEGER ); --字符串转换成日期时间类型 SELECT CAST ( '2008-08-08' AS DATETIME), CONVERT (DATETIME, '2008-08-08' ); SELECT DATEPART( YEAR , CAST ( '2008-08-08' AS DATETIME)); --数字转换成字符串 SELECT CONVERT ( varchar (50),123); SELECT FIdNumber, RIGHT (FIdNumber,3) AS 后三位, CAST ( RIGHT (FIdNumber,3) AS INTEGER ) AS 后三位的整数形式, CAST ( RIGHT (FIdNumber,3) AS INTEGER )+1 AS 后三位加一, CONVERT ( INTEGER , RIGHT (FIdNumber,3))/2 AS 后三位除以2 FROM T_Person; |
5、空值处理函数
ISNULL(expression,value):如果 expression 不为空则返回 expression,否则返回 value
--当记录中 FName 字段为 NULL 时显式“佚名” SELECT ISNULL (FName, '佚名' ) AS 姓名 FROM T_Employee; |
5、流控制函数
单值判断,相当于 switch-case
CASE expression
WHEN value1 THEN return_value1
WHEN value2 THEN return_value2
WHEN value3 THEN return_value3
ELSE default_return_value
END
CASE expression
WHEN value1 THEN return_value1
WHEN value2 THEN return_value2
WHEN value3 THEN return_value3
ELSE default_return_value
END
SELECT FName,( CASE FLevel WHEN 1 THEN 'VIP客户' WHEN 2 THEN '高级客户' WHEN 3 THEN '普通客户' ELSE '客户类型错误' END ) AS FLevelName FROM T_Customer; --范围判断 SELECT FName,( CASE WHEN FSalary<2000 THEN '低收入' WHEN FSalary>=2000 AND FSalary<=5000 THEN '中等收入' ELSE '高收入' END ) FROM T_Employee; |
练习
--有一张表T_Scroes,记录比赛成绩: --Date Name Scroe --2008-8-8 拜仁 胜 --2008-8-9 奇才 胜 --2008-8-8 湖人 胜 --2008-8-10 拜仁 负 --2008-8-8 拜仁 负 --2008-8-12 奇才 胜 --要求输出下面格式: --Name 胜 负 --拜仁 1 2 --湖人 1 0 --奇才 2 0 --注意:在中文字符串前加 N,比如 N'胜' --下面运算顺序: --先执行内层查询,得到如下中间结果集: --Name 胜 负 --拜仁 1 0 --奇才 1 0 --湖人 1 0 --拜仁 0 1 --拜仁 0 1 --奇才 1 0 --然后对中间结果集按队名 Name 进行分组,最后计算出每组“胜”字段的和与“负”字段的和。 SELECT Name , SUM ( CASE Score WHEN N '胜' THEN 1 ELSE 0 END ) AS 胜, SUM ( CASE Score WHEN N '负' THEN 1 ELSE 0 END ) AS 负 FROM T_Scroes GROUP BY Name ; |
--创建一张表T_Callers,记录电话呼叫员的工作流水,记录呼叫员编号、对方号码、通话开始时间、通话结束时间。建表、插数据等最后都自己写SQL语句。 --要求: -- 1) 输出所有数据中通话时间最长的5条记录。 -- 2) 输出所有数据中拨打长途号码(对方号码以0开头)的总时长。 -- 3) 输出本月通话总时长最多的前三个呼叫员的编号。 -- 4) 输出本月拨打电话次数最多的前三个呼叫员的编号。 -- 5) 输出所有数据的拨号流水,并且在最后一行添加总呼叫时长。 -- 记录呼叫员编号、对方号码、通话时长 -- ...... -- 汇总[市内号码总时长][长途号码总时长] --Id CallerNumber TellNumber StartDateTime EndDateTime --1 001 02088888888 2010-7-10 10:01 2010-7-10 10:05 --2 001 02088888888 2010-7-11 13:41 2010-7-11 13:52 --3 001 89898989 2010-7-11 14:42 2010-7-11 14:49 --4 002 02188368981 2010-7-13 21:04 2010-7-13 21:18 --5 002 76767676 2010-6-29 20:15 2010-6-29 20:30 --6 001 02288878243 2010-7-15 13:40 2010-7-15 13:56 --7 003 67254686 2010-7-13 11:06 2010-7-13 11:19 --8 003 86231445 2010-6-19 19:19 2010-6-19 19:25 --9 001 87422368 2010-6-19 19:25 2010-6-19 19:36 --10 004 40045862245 2010-6-19 19:50 2010-6-19 19:59 --创建数据表T_Callers. CREATE TABLE T_Callers (Id int NOT NULL , CallerNumber varchar (3), TellNumber varchar (13), StartDateTime datetime, EndDateTime datetime, PRIMARY KEY (Id)); --插入数据. INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (1, '001' , '02088888888' , '2010-7-10 10:01' , '2010-7-10 10:05' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (2, '002' , '02088888888' , '2010-7-11 13:41' , '2010-7-11 13:52' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (3, '003' , '89898989' , '2010-7-11 14:42' , '2010-7-11 14:49' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (4, '004' , '02188368981' , '2010-7-13 21:04' , '2010-7-13 21:18' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (5, '005' , '76767676' , '2010-6-29 20:15' , '2010-6-29 20:30' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (6, '006' , '02288878243' , '2010-7-15 13:40' , '2010-7-15 13:56' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (7, '007' , '67254686' , '2010-7-13 11:06' , '2010-7-13 11:19' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (8, '008' , '86231445' , '2010-6-19 19:19' , '2010-6-19 19:25' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (9, '009' , '87422368' , '2010-6-19 19:25' , '2010-6-19 19:36' ); INSERT INTO T_Callers(Id,CallerNumber,TellNumber,StartDateTime,EndDateTime) VALUES (10, '010' , '40045862245' , '2010-6-19 19:50' , '2010-6-19 19:59' ); --修改呼叫员编号. UPDATE T_Callers SET CallerNumber= '001' WHERE Id IN (1,2,3,6,9); UPDATE T_Callers SET CallerNumber= '002' WHERE Id IN (4,5); UPDATE T_Callers SET CallerNumber= '003' WHERE Id IN (7,8); UPDATE T_Callers SET CallerNumber= '004' WHERE Id=10; --题 1): --@计算通话时间; --@按通话时间降序排列; --@取前5条记录。 SELECT TOP 5 * FROM T_Callers ORDER BY DATEDIFF( SECOND ,StartDateTime,EndDateTime) DESC ; --题 2): --@查询拨打长途号码的记录; --@计算各拨打长途号码的通话时长; --@对各拨打长途号码的通话时长进行求和。 SELECT SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) AS 长途总时长 FROM T_Callers WHERE TellNumber LIKE '0%' ; --题 3):输出本月通话总时长最多的前三个呼叫员的编号. --@按呼叫员编号进行分组; --@计算各呼叫员通话总时长; --@按通话总时长进行降序排列; --@查询前3条记录中呼叫员的编号。 SELECT TOP 3 CallerNumber FROM T_Callers GROUP BY CallerNumber ORDER BY SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) DESC ; --题 4) 输出本月拨打电话次数最多的前三个呼叫员的编号. --@按呼叫员编号进行分组; --@计算个呼叫员拨打电话的次数; --@按呼叫员拨打电话的次数进行降序排序; --@查询前3条记录中呼叫员的编号。 SELECT TOP 3 CallerNumber FROM T_Callers GROUP BY CallerNumber ORDER BY COUNT (*) DESC ; --题5) 输出所有数据的拨号流水,并且在最后一行添加总呼叫时长: -- 记录呼叫员编号、对方号码、通话时长 -- ...... -- 汇总[市内号码总时长][长途号码总时长] --@计算每条记录中通话时长; --@查询包含不加 0 号码,即市内号码的记录; --@计算市内号码通话总时长; --@查询包含加 0 号码,即长途号码的记录; --@计算长途号码通话总时长; --@联合查询。 ( SELECT CallerNumber AS 呼叫员编号, TellNumber AS 对方号码, DATEDIFF( SECOND ,StartDateTime,EndDateTime) AS 通话时长 FROM T_Callers) UNION ( SELECT '汇总' , CAST ( SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) AS varchar ), CAST ( ( SELECT SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) FROM T_Callers WHERE TellNumber LIKE '0%' ) AS varchar ) FROM T_Callers WHERE TellNumber NOT LIKE '0%' ); --另一种查询汇总的方法: SELECT '汇总' , SUM ( CASE WHEN TellNumber NOT LIKE '0%' THEN DATEDIFF( SECOND ,StartDateTime,EndDateTime) ELSE 0 END ), SUM ( CASE WHEN TellNumber LIKE '0%' THEN DATEDIFF( SECOND ,StartDateTime,EndDateTime) ELSE 0 END ) FROM T_Callers; --题 1):输出所有数据中通话时间最长的5条记录. --@计算通话时间; --@按通话时间降序排列; --@取前5条记录。 SELECT TOP 5 * FROM T_Callers ORDER BY DATEDIFF( SECOND ,StartDateTime,EndDateTime) DESC ; --题 2):输出所有数据中拨打长途号码(对方号码以0开头)的总时长. --@查询拨打长途号码的结果集; --@计算各拨打长途号码的通话时长; --@对各拨打长途号码的通话时长进行求和。 SELECT SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) AS 长途总时长 FROM T_Callers WHERE TellNumber LIKE '0%' ; --题 3):输出本月通话总时长最多的前三个呼叫员的编号. --@按呼叫员编号进行分组; --@计算各呼叫员通话总时长; --@按通话总时长进行降序排列; --@查询前3条记录中呼叫员的编号。 SELECT TOP 3 CallerNumber FROM T_Callers GROUP BY CallerNumber ORDER BY SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) DESC ; --题 4) 输出本月拨打电话次数最多的前三个呼叫员的编号. --@按呼叫员编号进行分组; --@计算个呼叫员拨打电话的次数; --@按呼叫员拨打电话的次数进行降序排序; --@查询前3条记录中呼叫员的编号。 SELECT TOP 3 CallerNumber FROM T_Callers GROUP BY CallerNumber ORDER BY COUNT (*) DESC ; --题5) 输出所有数据的拨号流水,并且在最后一行添加总呼叫时长: -- 记录呼叫员编号、对方号码、通话时长 -- ...... -- 汇总[市内号码总时长][长途号码总时长] --@计算每条记录中通话时长; --@查询包含不加 0 号码,即市内号码的记录; --@计算市内号码通话总时长; --@查询包含加 0 号码,即长途号码的记录; --@计算长途号码通话总时长; --@联合查询。 ( SELECT CallerNumber AS 呼叫员编号, TellNumber AS 对方号码, DATEDIFF( SECOND ,StartDateTime,EndDateTime) AS 通话时长 FROM T_Callers) UNION ( SELECT '汇总' , CAST ( SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) AS varchar ), CAST ( ( SELECT SUM (DATEDIFF( SECOND ,StartDateTime,EndDateTime)) FROM T_Callers WHERE TellNumber LIKE '0%' ) AS varchar ) FROM T_Callers WHERE TellNumber NOT LIKE '0%' ); --另一种查询汇总的方法: SELECT '汇总' , SUM ( CASE WHEN TellNumber NOT LIKE '0%' THEN DATEDIFF( SECOND ,StartDateTime,EndDateTime) ELSE 0 END ), SUM ( CASE WHEN TellNumber LIKE '0%' THEN DATEDIFF( SECOND ,StartDateTime,EndDateTime) ELSE 0 END ) FROM T_Callers; |
分类:
SQL
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?