MSSQL扫盲系列(4)-系统函数

为了能够演示,先建立了三张表,具体SQL如下:

View Code
CREATE TABLE POSTTB (ID INT IDENTITY(1,1) PRIMARY KEY,NAME NVARCHAR(20) NOT NULL)
--职位对照表
INSERT INTO POSTTB VALUES('项目经理')
INSERT INTO POSTTB VALUES('架构师')
INSERT INTO POSTTB VALUES('开发人员')
INSERT INTO POSTTB VALUES('美工')
--插入数据

CREATE TABLE EMPLOYEETB(ID INT IDENTITY(1,1) PRIMARY KEY ,NAME NVARCHAR(20) NOT NULL)
--人员对照表
INSERT INTO EMPLOYEETB VALUES('周一仙')
INSERT INTO EMPLOYEETB VALUES('张小凡')
INSERT INTO EMPLOYEETB VALUES('碧瑶')
INSERT INTO EMPLOYEETB VALUES('陆雪琪')
INSERT INTO EMPLOYEETB VALUES('曾书书')
INSERT INTO EMPLOYEETB VALUES('云天河')
INSERT INTO EMPLOYEETB VALUES('韩菱纱')
INSERT INTO EMPLOYEETB VALUES('柳梦璃')
INSERT INTO EMPLOYEETB VALUES('慕容紫英')
INSERT INTO EMPLOYEETB VALUES('玄霄')
--插入数据,诛仙+仙4

CREATE TABLE SALARYTB (ID INT IDENTITY(1,1),
EMPLOYEETBID INT REFERENCES EMPLOYEETB(ID),
SALARY INT NOT NULL,
[MONTH] DATETIME NOT NULL,
[POSITION] INT REFERENCES POSTTB(ID))
--工资表

INSERT INTO SALARYTB VALUES(1,8500,'2012-1-1',1)
INSERT INTO SALARYTB VALUES(1,9500,'2012-2-1',1)
INSERT INTO SALARYTB VALUES(1,7500,'2012-3-1',1)

INSERT INTO SALARYTB VALUES(2,1800,'2012-1-1',3)
INSERT INTO SALARYTB VALUES(2,2000,'2012-2-1',3)
INSERT INTO SALARYTB VALUES(2,1800,'2012-3-1',3)

INSERT INTO SALARYTB VALUES(3,2100,'2012-1-1',4)
INSERT INTO SALARYTB VALUES(3,2500,'2012-2-1',4)
INSERT INTO SALARYTB VALUES(3,2200,'2012-3-1',4)

INSERT INTO SALARYTB VALUES(4,2100,'2012-1-1',4)
INSERT INTO SALARYTB VALUES(4,2800,'2012-2-1',4)
INSERT INTO SALARYTB VALUES(4,2000,'2012-3-1',4)

INSERT INTO SALARYTB VALUES(5,4000,'2012-1-1',2)
INSERT INTO SALARYTB VALUES(5,4100,'2012-2-1',2)
INSERT INTO SALARYTB VALUES(5,3900,'2012-3-1',2)

INSERT INTO SALARYTB VALUES(6,3100,'2012-1-1',3)
INSERT INTO SALARYTB VALUES(6,3500,'2012-2-1',3)
INSERT INTO SALARYTB VALUES(6,3000,'2012-3-1',3)

INSERT INTO SALARYTB VALUES(7,6500,'2012-1-1',1)
INSERT INTO SALARYTB VALUES(7,7000,'2012-2-1',1)
INSERT INTO SALARYTB VALUES(7,7200,'2012-3-1',1)

INSERT INTO SALARYTB VALUES(8,3500,'2012-1-1',4)
INSERT INTO SALARYTB VALUES(8,3400,'2012-2-1',4)
INSERT INTO SALARYTB VALUES(8,3200,'2012-3-1',4)

INSERT INTO SALARYTB VALUES(9,4300,'2012-1-1',2)
INSERT INTO SALARYTB VALUES(9,4200,'2012-2-1',2)
INSERT INTO SALARYTB VALUES(9,4700,'2012-3-1',2)

INSERT INTO SALARYTB VALUES(10,2800,'2012-1-1',3)
INSERT INTO SALARYTB VALUES(10,2300,'2012-2-1',3)
INSERT INTO SALARYTB VALUES(10,2100,'2012-3-1',3)
--插入数据

最常用的几个聚合函数 

AVG--求平局值

View Code
--职位薪水检查

--查询每种职位每月的平均薪水
SELECT POSTTB.NAME 职位,MONTH(SALARYTB.[MONTH]) 月份,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB
JOIN POSTTB ON SALARYTB.POSITION=POSTTB.ID
GROUP BY SALARYTB.POSITION,SALARYTB.[MONTH],POSTTB.NAME
ORDER BY 平均工资 DESC

SELECT POSTTB.NAME 职位,MONTH(SALARYTB.[MONTH]) 月份,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB,POSTTB
WHERE SALARYTB.POSITION=POSTTB.ID
GROUP BY SALARYTB.POSITION,SALARYTB.[MONTH],POSTTB.NAME
ORDER BY 平均工资 DESC

--查询每种职位1月的平均薪水
SELECT POSTTB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB JOIN POSTTB ON SALARYTB.POSITION=POSTTB.ID
WHERE MONTH(SALARYTB.[MONTH])=1
GROUP BY SALARYTB.POSITION ,POSTTB.NAME
ORDER BY 平均工资 DESC

SELECT POSTTB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB,POSTTB
WHERE SALARYTB.POSITION=POSTTB.ID AND MONTH(SALARYTB.[MONTH])=1
GROUP BY SALARYTB.POSITION ,POSTTB.NAME
ORDER BY 平均工资 DESC

--查询每种职位这三个月的平均薪水
SELECT POSTTB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB
JOIN POSTTB ON SALARYTB.POSITION=POSTTB.ID
GROUP BY SALARYTB.POSITION ,POSTTB.NAME
ORDER BY 平均工资 DESC

SELECT POSTTB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB,POSTTB
WHERE SALARYTB.POSITION=POSTTB.ID
GROUP BY SALARYTB.POSITION ,POSTTB.NAME
ORDER BY 平均工资 DESC

--个人薪水检查

--查询所有人三个月的平均薪水
SELECT EMPLOYEETB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB JOIN EMPLOYEETB ON SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
GROUP BY SALARYTB.EMPLOYEETBID ,EMPLOYEETB.NAME
ORDER BY 平均工资 DESC

SELECT EMPLOYEETB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB , EMPLOYEETB WHERE SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
GROUP BY SALARYTB.EMPLOYEETBID ,EMPLOYEETB.NAME
ORDER BY 平均工资 DESC

--查询所有人前两个月的平均薪水
SELECT EMPLOYEETB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB JOIN EMPLOYEETB ON SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
WHERE MONTH(SALARYTB.[MONTH]) BETWEEN 1 AND 2
GROUP BY SALARYTB.EMPLOYEETBID ,EMPLOYEETB.NAME
ORDER BY 平均工资 DESC

SELECT EMPLOYEETB.NAME 职位,AVG(SALARYTB.SALARY) AS 平均工资
FROM SALARYTB , EMPLOYEETB
WHERE SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID AND MONTH(SALARYTB.[MONTH]) BETWEEN 1 AND 2
GROUP BY SALARYTB.EMPLOYEETBID ,EMPLOYEETB.NAME
ORDER BY 平均工资 DESC

 COUNT--计数

View Code
--获取所有人数
SELECT COUNT(DISTINCT E.NAME) 人数 FROM EMPLOYEETB E

--获取每个职位上的人数
SELECT POSTTB.NAME 职位,COUNT(DISTINCT SALARYTB.EMPLOYEETBID) 人数
FROM SALARYTB
JOIN POSTTB ON SALARYTB.POSITION=POSTTB.ID
GROUP BY POSTTB.NAME

SELECT POSTTB.NAME 职位,COUNT(DISTINCT SALARYTB.EMPLOYEETBID) 人数
FROM SALARYTB,POSTTB
WHERE SALARYTB.POSITION=POSTTB.ID
GROUP BY POSTTB.NAME


--后面这一部分是附带的
--
获取每个职位上的人
SELECT DISTINCT POSTTB.NAME 职位 ,EMPLOYEETB.NAME 姓名
FROM SALARYTB
JOIN EMPLOYEETB ON SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
JOIN POSTTB ON SALARYTB.[POSITION]=POSTTB.ID
--直接使用DISTINCT
;WITH T AS
(SELECT POSTTB.NAME 职位 ,EMPLOYEETB.NAME 姓名
FROM SALARYTB
JOIN EMPLOYEETB ON SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
JOIN POSTTB ON SALARYTB.[POSITION]=POSTTB.ID)
SELECT * FROM T UNION SELECT * FROM T
--消除重复列
;WITH T AS
(SELECT POSTTB.NAME 职位 ,EMPLOYEETB.NAME 姓名
FROM SALARYTB
JOIN EMPLOYEETB ON SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
JOIN POSTTB ON SALARYTB.[POSITION]=POSTTB.ID)
SELECT * FROM T INTERSECT SELECT * FROM T
--消除重复列

--合并列
;WITH T AS
(SELECT DISTINCT POSTTB.NAME 职位 ,EMPLOYEETB.NAME 姓名
FROM SALARYTB
JOIN EMPLOYEETB ON SALARYTB.EMPLOYEETBID=EMPLOYEETB.ID
JOIN POSTTB ON SALARYTB.[POSITION]=POSTTB.ID)
SELECT 职位,姓名 FROM(
SELECT DISTINCT 职位 FROM T
) A
OUTER APPLY(
SELECT
[姓名]= STUFF(
REPLACE(
REPLACE(
(SELECT 姓名 FROM T WHERE 职位 = A.职位 FOR XML AUTO),
'<T 姓名="', ','),
'"/>', ''),
1, 1, '')
)N
--这个比较有难度

 SUM--求和

View Code
--求公司每个月分别发出多少薪水
SELECT MONTH(S.[MONTH]) 月份, SUM(S.SALARY) 总薪水
FROM SALARYTB S
GROUP BY S.[MONTH]

--求公司1月发出多少薪水
SELECT MONTH(S.[MONTH]) 月份, SUM(S.SALARY) 总薪水
FROM SALARYTB S WHERE MONTH(S.[MONTH])=1
GROUP BY S.[MONTH]

--求每个员工三个月总共领了多少薪水
SELECT E.NAME 姓名, SUM(S.SALARY) 总薪水
FROM SALARYTB S
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
GROUP BY E.NAME
ORDER BY 总薪水 DESC

--求每个职位三个月总共领了多少薪水
SELECT P.NAME 姓名, SUM(S.SALARY) 总薪水
FROM SALARYTB S
JOIN POSTTB P ON S.POSITION=P.ID
GROUP BY P.NAME
ORDER BY 总薪水 DESC

--求每个职位每个月总共领了多少薪水
SELECT P.NAME 姓名,MONTH(S.[MONTH]) 月份,SUM(S.SALARY) 总薪水
FROM SALARYTB S
JOIN POSTTB P ON S.POSITION=P.ID
GROUP BY P.NAME,S.[MONTH]
ORDER BY 总薪水 DESC

 MAX,MIN--最大最小值(这一部分是有一些难度)

View Code
--查询每个员工最高薪水的月份
WITH T AS (
SELECT MAX(S.SALARY) SALARY,S.EMPLOYEETBID ID
FROM SALARYTB S
GROUP BY S.EMPLOYEETBID)
SELECT E.NAME 姓名, MONTH(S.[MONTH]) 月份,T.SALARY 薪水
FROM T
JOIN EMPLOYEETB E ON T.ID=E.ID
JOIN SALARYTB S ON S.SALARY=T.SALARY AND S.EMPLOYEETBID=T.ID


WITH T AS (
SELECT MIN(S.SALARY) SALARY,S.EMPLOYEETBID ID
FROM SALARYTB S
GROUP BY S.EMPLOYEETBID)
SELECT E.NAME 姓名, MONTH(S.[MONTH]) 月份,T.SALARY 薪水
FROM T
JOIN EMPLOYEETB E ON T.ID=E.ID
JOIN SALARYTB S ON S.SALARY=T.SALARY AND S.EMPLOYEETBID=T.ID

--求各月工资最高最低的人
SELECT MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM
(SELECT MAX(S.SALARY) SALARY,S.[MONTH]
FROM SALARYTB S GROUP BY S.[MONTH] ) T
JOIN SALARYTB S ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH]
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
ORDER BY 月份

SELECT MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM
(SELECT MIN(S.SALARY) SALARY,S.[MONTH]
FROM SALARYTB S GROUP BY S.[MONTH] ) T
JOIN SALARYTB S ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH]
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
ORDER BY 月份


;WITH T AS (
SELECT S.[MONTH] 月份,MAX(S.SALARY) 薪水
FROM SALARYTB S
GROUP BY S.[MONTH]
)
SELECT MONTH(S.[MONTH]) 月份,E.NAME 姓名,S.SALARY 薪水
FROM SALARYTB S
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
WHERE S.SALARY IN (SELECT 薪水 FROM T)
ORDER BY 月份

;WITH T AS (
SELECT S.[MONTH] 月份,MIN(S.SALARY) 薪水
FROM SALARYTB S
GROUP BY S.[MONTH]
)
SELECT MONTH(S.[MONTH]) 月份,E.NAME 姓名,S.SALARY 薪水
FROM SALARYTB S JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
WHERE S.SALARY IN (SELECT 薪水 FROM T)
ORDER BY 月份

SELECT MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM
(SELECT MAX(S.SALARY) SALARY,S.[MONTH]
FROM SALARYTB S GROUP BY S.[MONTH] ) T
JOIN SALARYTB S ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH]
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
ORDER BY 月份

--查出每个部门每月薪水最高最低的人
WITH T AS (
SELECT MAX(S.SALARY) SALARY,S.[MONTH] [MONTH],S.POSITION POSTION
FROM SALARYTB S GROUP BY S.[MONTH],S.POSITION
)
SELECT P.NAME 部门, MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM SALARYTB S
JOIN T ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH] AND S.POSITION=T.POSTION
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
JOIN POSTTB P ON S.POSITION=P.ID
ORDER BY 部门,月份

SELECT P.NAME 部门,MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM (
SELECT MAX(S.SALARY) SALARY,S.[MONTH] [MONTH],S.POSITION POSTION
FROM SALARYTB S GROUP BY S.[MONTH],S.POSITION
) T
JOIN SALARYTB S ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH] AND S.POSITION=T.POSTION
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
JOIN POSTTB P ON S.POSITION=P.ID
ORDER BY 部门,月份



WITH T AS (
SELECT MIN(S.SALARY) SALARY,S.[MONTH] [MONTH],S.POSITION POSTION
FROM SALARYTB S GROUP BY S.[MONTH],S.POSITION
)
SELECT P.NAME 部门, MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM SALARYTB S
JOIN T ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH] AND S.POSITION=T.POSTION
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
JOIN POSTTB P ON S.POSITION=P.ID
ORDER BY 部门,月份

SELECT P.NAME 部门,MONTH(S.[MONTH]) 月份, T.SALARY 薪水,E.NAME 姓名 FROM (
SELECT MIN(S.SALARY) SALARY,S.[MONTH] [MONTH],S.POSITION POSTION
FROM SALARYTB S GROUP BY S.[MONTH],S.POSITION
) T
JOIN SALARYTB S ON T.SALARY=S.SALARY AND S.[MONTH] = T.[MONTH] AND S.POSITION=T.POSTION
JOIN EMPLOYEETB E ON S.EMPLOYEETBID=E.ID
JOIN POSTTB P ON S.POSITION=P.ID
ORDER BY 部门,月份

 CONVERT

View Code
SELECT CONVERT(BIT,'1')
--将整数字符串转化为BIT,负数不能转,只有'0'才能转换为0,其他的都是1
SELECT CONVERT(INT,'-100'),CONVERT(INT,'0'),CONVERT(INT,'23')
--将整数字符串转化为INT
SELECT CONVERT(FLOAT,'12.023'),CONVERT(REAL,'89.145')
--将整数字符串转化为FLOAT,REAL
SELECT CONVERT(NVARCHAR(2),12),CONVERT(NVARCHAR(5),12.67),CONVERT(NVARCHAR,12.67777)
--将数转化为字符串,长度可选

SELECT CONVERT(DATETIME,'2012-8-9')
--转换字符串为日期
--
--
转换日期为字符串的格式很多
--
放个临时表,来看一下
CREATE TABLE #(原值 DATETIME,代号 INT,结果 NVARCHAR(100))
DECLARE @D DATETIME
SET @D=GETDATE()
DECLARE @I INT
SET @I=0
WHILE @I<132
BEGIN
INSERT INTO # SELECT @D,@I, CONVERT(NVARCHAR(100), @D, @I)
SET @I=@I+1
IF @I=15
SET @I=20
IF @I=26
SET @I=100
IF @I=115
SET @I=120
IF @I=122
SET @I=130
END
INSERT INTO # SELECT @D,126, CONVERT(NVARCHAR(100), @D, 126)
SELECT * FROM # ORDER BY 代号
DROP TABLE #--及时干掉临时表,是个好习惯

其他常用函数

View Code
--ISNULL
SELECT ISNULL(NULL,'DEFAULTVALE'),ISNULL(12,'DEFAULTVALE')
--检测第一个参数是否为空,如果为空,则使用后面的默认,否则就返回第一个参数值

--数学函数

--RAND
SELECT RAND(),CONVERT(INT,RAND()*10),100+CONVERT(INT,RAND()*50)
--获取随机小数,随机整数[0-10],[100-150]

--日期函数

--GETDATE,ISDATE
SELECT GETDATE(),ISDATE('2012-8-9'),ISDATE('45546')
--获取当前时间,检查所给字符串是否是日期,返回bit值

--YEAR,MONTH,DAY
SELECT YEAR(GETDATE()),MONTH(GETDATE()),DAY(GETDATE()),
DATEDIFF(YEAR,'2011','2012-8-9'),DATEDIFF(YEAR,'2011-1-2','2990-2-3'),
DATEDIFF(MONTH,'2011-3-1','2012-8-9'),DATEDIFF(MONTH,'2011-1-2','2990-2-3'),
DATEDIFF(DAY,'2011-3-1','2011-8-9'),DATEDIFF(DAY,'2011-1-2','2011-1-3')
--返回所给日期的的年,月,日,根据所给参数求出两个日期之间的差值(年,月,日)


--字符串函数

--LEN
SELECT LEN('ABCD'),LEN('迷途小码农')
--获取字符串长度

--CHAR,NCHAR
SELECT CHAR(65),CHAR(66),CHAR(67),
NCHAR(20474),NCHAR(32769),
NCHAR(23385),NCHAR(21435),NCHAR(20063)
--将ASCII,UNICODE码转成字符

--CHARINDEX
SELECT CHARINDEX('','迷途小码农'),CHARINDEX('','迷途小码农'),
CHARINDEX('D','ABCDEDD',5),CHARINDEX('DE','ABCDEDD')
--从字符串中查找子串,第三个参数是起始位置,如果没有则返回0

--LEFT,RIGHT,SUBSTRING
SELECT LEFT(N'ABCDEFG',3),RIGHT(N'ABCDEFG',3),SUBSTRING(N'ABCDEFG',0,2)
--返回所给字符串的左右端的几个字符所组成的串,截取字符串

--LOWER,UPPER
SELECT LOWER('ABCDEF'),UPPER('abcdef')
--转化为大小写

--LTRIM,RTRIM
SELECT LTRIM(' ABC '),RTRIM(' ABC '),LTRIM(RTRIM(' ABC ')),
LEN(LTRIM(' ABC ')),LEN(RTRIM(' ABC ')),LEN(LTRIM(RTRIM(' ABC ')))
--剔除左右空格

--REPLACE,REVERSE,STUFF
SELECT REPLACE('ABCD','A','B'),REVERSE('ABCD'),
STUFF('ABCDEFGHIJKLMN',2,5,'--')
--替换,逆转,使用新串替换定长串

 

posted @ 2012-03-10 10:02  方外老和尚  阅读(...)  评论(...编辑  收藏