MSSQL扫盲系列(3)-SELECT

作者:Aimuti  发布日期:2012-03-14 13:34:44


MSSQL扫盲系列(开篇)  
MSSQL扫盲系列(1)-CREATE,ALTER,DROP
MSSQL扫盲系列(2)-INSERT,UPDATE,DELETE
MSSQL扫盲系列(3)-SELECT  
MSSQL扫盲系列(4)-系统函数
MSSQL扫盲系列(5)-常量,变量,运算符,流程控制
MSSQL扫盲系列(6)-异常,事物,函数,存储过程 




SELECT是个大话题,分成单独一篇

基本查找

SELECT * FROM USERS
--查询全部数据
SELECT * FROM USERS WHERE USERNAME LIKE 'K%'
--查询所有用户名以K打头用户的全部信息
SELECT TOP 1 * FROM USERS WHERE USERNAME LIKE 'K%'
--查询第一个用户名以K打头用户的全部信息
SELECT USERNAME,[PASSWORD],AGE=DATEDIFF(YEAR,BIRTHDAY,GETDATE()) FROM USERS  WHERE USERNAME LIKE 'K%'
--DATEDIFF(YEAR,BIRTHDAY,GETDATE())可以用来求年龄
--查询所有用户名以K打头用户的部分信息
SELECT @@IDENTITY
--史上最短查询,用的非常多的查询
SELECT ROWID=IDENTITY(INT,1,1),USERNAME,[PASSWORD] INTO # FROM USERS 
--带计数的查询
SELECT * FROM #
DROP TABLE #

条件

 

SELECT DISTINCT USERNAME FROM USERS
--获得不重复用户名
SELECT TOP 10 USERNAME FROM USERS
--TOP 是优化SQL的一个很好的选择
SELECT TOP 10 * FROM USERS WHERE ID NOT IN(SELECT TOP 30 ID FROM USERS)
--简单的SQL分页,使用IN,在有限的范围查找数据
SELECT * FROM USERS WHERE  EXISTS(SELECT TOP 1 1 FROM AREA WHERE ID= [ADDRESS])
--使用EXISTS,判断是否存在
SELECT TOP 10 * FROM USERS WHERE BIRTHDAY BETWEEN '1800-1-1' AND '2000-1-1'
--使用BETWEEN AND 查询位于某范围的值
SELECT * FROM USERS WHERE USERNAME LIKE 'K%'
--使用LIKE,查询所有用户名以K打头用户的全部信息,
--具体通配符请转到 http://www.w3school.com.cn/sql/sql_wildcards.asp

排序 


SELECT TOP 10 * FROM USERS 
--数据原样
SELECT TOP 10 * FROM USERS ORDER BY USERNAME ASC
--顺序查找记录,ASC可以省略
SELECT TOP 10 * FROM USERS ORDER BY USERNAME DESC
--倒序查找
SELECT TOP 10 * FROM USERS ORDER BY USERNAME DESC,GENDER ASC
--使用用户名倒序,性别顺序(这个貌似说不过去,能懂就行)

分组


--###################################################
--GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组##
--###################################################
SELECT TOP 20 USERNAME FROM USERS GROUP BY USERNAME
SELECT TOP 20 USERNAME FROM USERS ORDER BY USERNAME
--这个GROUP BY 和ORDER BY USERNAME DESC 效果相同
--现在来个比较面试的,数据如下
CREATE TABLE #([NAME] NVARCHAR(50) NOT NULL,SALE INT NOT NULL)
--临时表,人名,工资
INSERT INTO # ([NAME],SALE) VALUES ('B',100)
INSERT INTO # ([NAME],SALE) VALUES ('B',1000)
INSERT  INTO # ([NAME],SALE) VALUES ('A',5)
INSERT INTO # ([NAME],SALE) VALUES ('A',50)
INSERT INTO # ([NAME],SALE) VALUES ('C',2)
INSERT INTO # ([NAME],SALE) VALUES ('C',20)
INSERT INTO # ([NAME],SALE) VALUES ('B',1)
INSERT INTO # ([NAME],SALE) VALUES ('B',10)
INSERT INTO # ([NAME],SALE) VALUES ('A',500)
INSERT INTO # ([NAME],SALE) VALUES ('A',5000)
INSERT INTO # ([NAME],SALE) VALUES ('C',200)
INSERT INTO # ([NAME],SALE) VALUES ('C',2000)
--插入一些数据
SELECT * FROM #
--所有数据
SELECT SUM(SALE) S,[NAME] FROM # GROUP BY [NAME] 
--获得每个人的总工资
SELECT [NAME] FROM # GROUP BY [NAME] HAVING SUM(SALE) >2000
--获取总工资大于2000的人名
SELECT NAME,SALE FROM # GROUP BY NAME,SALE
--按人名和工资分组
DROP TABLE #

JOIN


CREATE TABLE #(FK INT NOT NULL,FA CHAR(1) NOT NULL)
CREATE TABLE ##(FK INT NOT NULL,FA CHAR(1) NOT NULL)
--建了两个临时表,一个本地,一个全局
INSERT INTO # VALUES(1,'A')
INSERT INTO # VALUES(3,'B')
INSERT INTO # VALUES(4,'C')

SELECT * FROM #

INSERT INTO ## VALUES(1,'X')
INSERT INTO ## VALUES(2,'Y')
INSERT INTO ## VALUES(4,'Z')

SELECT * FROM ##

--插入数据

SELECT A.FK,A.FA,B.FK,B.FA FROM # A ,## B
SELECT A.FK,A.FA,B.FK,B.FA FROM # A CROSS JOIN ##  B 
--两种的写法不同,但是效果一样,都是求笛卡尔积

SELECT A.FK,A.FA,B.FK,B.FA FROM # A ,## B WHERE  A.FK=B.FK
SELECT A.FK,A.FA,B.FK,B.FA FROM # A  INNER JOIN ##  B ON A.FK=B.FK
--两种的写法不同,但是效果一样,都是内部链接

SELECT A.FK,A.FA,B.FK,B.FA FROM # A LEFT JOIN ##  B ON A.FK=B.FK
SELECT A.FK,A.FA,B.FK,B.FA FROM # A LEFT OUTER JOIN ##  B ON A.FK=B.FK
--两种的写法不同,但是效果一样,都是左外连接
--此处获得数据条目和本地临时表A相同

SELECT A.FK,A.FA,B.FK,B.FA FROM # A RIGHT JOIN ##  B ON A.FK=B.FK
SELECT A.FK,A.FA,B.FK,B.FA FROM # A RIGHT OUTER JOIN ##  B ON A.FK=B.FK
--两种的写法不同,但是效果一样,都是右外连接
--此处获得数据条目和全局临时表B相同

SELECT A.FK,A.FA,B.FK,B.FA FROM # A FULL JOIN ##  B ON A.FK=B.FK
SELECT A.FK,A.FA,B.FK,B.FA FROM # A FULL OUTER JOIN ##  B ON A.FK=B.FK
--两种的写法不同,但是效果一样,都是全连接
--此处获得数据条目是AB两表中连接键的不重复总数

DROP TABLE #,##

UNION


CREATE TABLE #(FK INT NOT NULL,FA CHAR(1) NOT NULL)
CREATE TABLE ##(FK INT NOT NULL,FA CHAR(1) NOT NULL)
--还是两个临时表

INSERT INTO # VALUES(1,'A')
INSERT INTO # VALUES(3,'B')
INSERT INTO # VALUES(4,'C')

SELECT * FROM #

INSERT INTO ## VALUES(1,'A')
INSERT INTO ## VALUES(1,'X')
INSERT INTO ## VALUES(2,'Y')
INSERT INTO ## VALUES(4,'Z')

SELECT * FROM ##

--插入数据
--#########################################
--UNION 求并集,INTERSECT求交集,EXCEPT求差集######
--#########################################
SELECT * FROM #  UNION SELECT * FROM ## ORDER BY FA
--合并两个SQL结果并消除重复记录,字段数要相等
SELECT * FROM # UNION ALL  SELECT * FROM ## ORDER BY FA
--合并两个SQL结果不消除重复记录,字段数要相等
SELECT * FROM #  INTERSECT SELECT * FROM ## ORDER BY FA
--求两个SQL结果的相同数据,字段数要相等
SELECT * FROM #  EXCEPT SELECT * FROM ## ORDER BY FA
--求两个SQL结果的差集,即第一个结果中第二个结果没有的部分
DROP TABLE #,##

附加部分

CASE


CREATE TABLE #(GENDER BIT)

INSERT INTO # SELECT CASE 
                                        WHEN RAND()>0.5 THEN 0 
                                        ELSE 1 
                                    END 
--第一个CASE
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
INSERT INTO # SELECT CASE WHEN RAND()>0.5 THEN 0 ELSE 1 END 
--0男,1女

SELECT * FROM #

SELECT 性别= CASE 
                        WHEN GENDER=0 THEN '男'
                        WHEN GENDER=1 THEN '女'
                        ELSE ''
                    END
    FROM #
--第二个CASE

DROP TABLE #

WITH(更多,点击HERE)

为了能演示,这里新建了两张表,详细SQL如下

 

CREATE TABLE T1 (ID INT IDENTITY(1,1) PRIMARY KEY,[ADDRESS] NVARCHAR(3))
CREATE TABLE T2 (ID INT IDENTITY(1,1) PRIMARY KEY,
                            USERNAME NVARCHAR(10) NOT NULL,
                            ADDRESSID INT REFERENCES T1(ID)
)
--创建两个表,因为不能为临时表建立外键,所以必须是真实表
DECLARE @I INT
SET @I=0
WHILE @I<=100
    BEGIN
        INSERT INTO T1 VALUES(CHAR(65+RAND()*25)+CHAR(65+RAND()*25)+CHAR(65+RAND()*25))
        SET @I=@I+1
    END

--为第一个表插入数据
SET @I=0
WHILE @I<=200
    BEGIN
        INSERT INTO T2 VALUES(CHAR(65+RAND()*25)+CHAR(65+RAND()*25),1+CONVERT(INT,RAND()*100) )
        SET @I=@I+1
    END
    --为第二个表插入数据
--DROP TABLE T2, T1
--删除做的准备

开始正题


--需要查询居住地地名[ADDRESS]以C开头的所有人信息
--从数据库的样子看,必须得从两个表里查了

--两个表JOIN一下么,OK
SELECT T2.* FROM T2 JOIN T1 ON T2.ADDRESSID=T1.ID WHERE T1.[ADDRESS] LIKE 'C%'
--结果出来了

--啊哈,还好有子查询,于是
SELECT T2.* FROM T2 WHERE T2.ADDRESSID IN ( SELECT ID FROM T1 WHERE T1.[ADDRESS] LIKE 'C%')
--先从T1中查找所有以C开头的地名主键
--再从它中查找出对于地名主键的人信息

--纳尼,还有其他方法,是的
--据目测,中间数据的结果不是很多,用表变量吧
DECLARE @T TABLE(ID INT)
--定义了表变量
INSERT INTO @T SELECT ID  FROM T1 WHERE [ADDRESS]  LIKE 'C%' 
--先从T1中查找所有以C开头的地名主键,并放置到这个临时表里
SELECT * FROM T2 WHERE ADDRESSID  IN (SELECT ID FROM @T)
--再从StateProvince查询出这些州代码所对应的州信息

--伟大的WITH现身
;WITH T AS (SELECT ID  FROM T1 WHERE [ADDRESS]  LIKE 'C%' )
--和上面的方法貌似很像
SELECT * FROM T2 WHERE ADDRESSID  IN (SELECT ID FROM T)
--一样能查出

分页


--使用ID大小和TOP分页,最好的效率
SELECT TOP 10--页大小
            USERNAME,[PASSWORD] --查询字段
            FROM USERS --表名
            WHERE ID >=(
                                SELECT ISNULL(MAX(ID),0) FROM (
                                SELECT TOP 30--页大小*页码-1 [10*(4-1)]
                                          ID FROM USERS ORDER BY ID ) T --别名T必须
                                  )  ORDER BY ID
                                  
--使用ID和TOP分页,效率次之
SELECT TOP 10--页大小
            USERNAME,[PASSWORD] --查询字段
            FROM USERS --表名
            WHERE ID NOT IN (
                                SELECT TOP 30--页大小*页码-1 [10*(4-1)]
                                          ID FROM USERS --ORDER BY ID可选
                                         ) --ORDER BY ID可选

--使用ROW_NUMBER()
SELECT TOP 10 USERNAME,[PASSWORD]  FROM 
(SELECT ROW_NUMBER() OVER (ORDER BY ID) ROWID,USERNAME,[PASSWORD]  FROM USERS)
 T WHERE ROWID BETWEEN 30 AND 40 
--子查询 
;WITH T AS (SELECT ROW_NUMBER() OVER (ORDER BY ID) ROWID,USERNAME,[PASSWORD]  FROM USERS)
SELECT TOP 10 USERNAME,[PASSWORD]  FROM T WHERE ROWID >30 
--WITH加简单条件
;WITH T AS (SELECT ROW_NUMBER() OVER (ORDER BY ID) ROWID,USERNAME,[PASSWORD]  FROM USERS)
SELECT TOP 10 USERNAME,[PASSWORD]  FROM T WHERE ROWID BETWEEN 30 AND 40 
--WITH加BETWEEN

MSSQL扫盲系列(开篇)  
MSSQL扫盲系列(1)-CREATE,ALTER,DROP
MSSQL扫盲系列(2)-INSERT,UPDATE,DELETE
MSSQL扫盲系列(3)-SELECT  
MSSQL扫盲系列(4)-系统函数
MSSQL扫盲系列(5)-常量,变量,运算符,流程控制
MSSQL扫盲系列(6)-异常,事物,函数,存储过程 

Tag标签: MSSQL扫盲  
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规