SQL 100+个最佳入门案例实践(覆盖Oralce、SQL Server、Mysql)之基础操作_1_检索数据
SQL基礎操作_1_檢索數據
目錄
7.1.1?數據集
7.1.2 學生選課關系表
7.1.3 供應商關系表
7.2.1 從表中查詢所有行和列
7.2.2 從表中查詢部分行
7.2.3 查詢滿足某個條件行
7.2.4 從表中查詢部分列
7.2.5 給字段取個有意義的名字
7.2.6 結合where使用別名
7.2.7 拼接列的值
7.2.8 查詢語句里執行條件判斷
7.2.9 返回的字段在某個范圍內的數據
7.2.10 通過多條件組合返回數據
7.2.11 限制返回的行數
7.2.12 從表中隨機返回N條記錄
7.2.13 從表中查詢空值
7.2.14 返回不重復的記錄
7.2.15 將空值轉成其它值
7.2.16 按照某個模式搜索
7.2.17 按照指定的次序返回查詢結果
7.2.18 按照多個字段排序查詢結果
7.2.19 按照字符串對結果排序
7.2.20 按照字符串數字組合的排序
7.2.21 處理空值的排序
7.2.22 根據數據項的值排序
?
7.1.1?數據集
見如下SQL,以Oracle為例:
-- 1 Oracle版本 -- DROP TABLE EMP; -- DROP TABLE DEPT; -- DROP TABLE BONUS; -- DROP TABLE SALGRADE;CREATE TABLE DEPT (DEPTNO NUMBER(2) NOT NULL CONSTRAINT pk_dept_deptno primary key, DNAME VARCHAR2(14), LOC VARCHAR2(13) );comment on table DEPT is '部門表'; comment on column DEPT.DEPTNO is '表示部門編號,由兩位數字所組成'; comment on column DEPT.DNAME is '部門名稱,最多由14個字符所組成'; comment on column DEPT.LOC is '部門所在的位置';INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS'); INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO'); INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL CONSTRAINT pk_emp_empno primary key, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7, 2), COMM NUMBER(7, 2), DEPTNO NUMBER(2) constraint dept_deptno_ref references dept(deptno) );comment on table EMP is '雇員表'; comment on column EMP.EMPNO is '雇員的編號,由四位數字所組成'; comment on column EMP.ENAME is '雇員的姓名,由10位字符所組成'; comment on column EMP.JOB is '雇員的職位'; comment on column EMP.MGR is '雇員對應的領導編號,領導也是雇員'; comment on column EMP.HIREDATE is '雇員的雇傭日期'; comment on column EMP.SAL is '基本工資,其中有兩位小數,五倍整數,一共是七位'; comment on column EMP.COMM is '獎金,傭金'; comment on column EMP.DEPTNO is '雇員所在的部門編號';INSERT INTO EMP VALUES(7369, 'SMITH', 'CLERK', 7902,TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20); INSERT INTO EMP VALUES(7499, 'ALLEN', 'SALESMAN', 7698,TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30); INSERT INTO EMP VALUES(7521, 'WARD', 'SALESMAN', 7698,TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30); INSERT INTO EMP VALUES(7566, 'JONES', 'MANAGER', 7839,TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20); INSERT INTO EMP VALUES(7654, 'MARTIN', 'SALESMAN', 7698,TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30); INSERT INTO EMP VALUES(7698, 'BLAKE', 'MANAGER', 7839,TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30); INSERT INTO EMP VALUES(7782, 'CLARK', 'MANAGER', 7839,TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10); INSERT INTO EMP VALUES(7788, 'SCOTT', 'ANALYST', 7566,TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES(7839, 'KING', 'PRESIDENT', NULL,TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10); INSERT INTO EMP VALUES(7844, 'TURNER', 'SALESMAN', 7698,TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30); INSERT INTO EMP VALUES(7876, 'ADAMS', 'CLERK', 7788,TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20); INSERT INTO EMP VALUES(7900, 'JAMES', 'CLERK', 7698,TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30); INSERT INTO EMP VALUES(7902, 'FORD', 'ANALYST', 7566,TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES(7934, 'MILLER', 'CLERK', 7782,TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);CREATE TABLE BONUS (ENAME VARCHAR2(10), JOB VARCHAR2(9), SAL NUMBER, COMM NUMBER);comment on table BONUS is '獎金表'; comment on column BONUS.ENAME is '雇員姓名'; comment on column BONUS.JOB is '雇員職位'; comment on column BONUS.SAL is '雇員的工資'; comment on column BONUS.COMM is '雇員的獎金';CREATE TABLE SALGRADE (GRADE NUMBER, LOSAL NUMBER, HISAL NUMBER);comment on table SALGRADE is '工資等級表'; comment on column SALGRADE.GRADE is '工資的等級'; comment on column SALGRADE.LOSAL is '此等級的最低工資'; comment on column SALGRADE.HISAL is '此等級的最高工資';INSERT INTO SALGRADE VALUES (1, 700, 1200); INSERT INTO SALGRADE VALUES (2, 1201, 1400); INSERT INTO SALGRADE VALUES (3, 1401, 2000); INSERT INTO SALGRADE VALUES (4, 2001, 3000); INSERT INTO SALGRADE VALUES (5, 3001, 9999);COMMIT;-- 2 Mysql 版本 DROP TABLE IF EXISTS emp; DROP TABLE IF EXISTS dept; DROP TABLE IF EXISTS bonus; DROP TABLE IF EXISTS salgrade; create table dept(deptno int unsigned auto_increment COMMENT '部門編號',dname varchar(15) COMMENT '部門名稱',loc varchar(50) COMMENT '部門所在位置', primary key(deptno) ) COMMENT='部門表';INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK'); INSERT INTO dept VALUES (20,'RESEARCH','DALLAS'); INSERT INTO dept VALUES (30,'SALES','CHICAGO'); INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');create table emp(empno int unsigned auto_increment COMMENT '雇員編號',ename varchar(15) COMMENT '雇員姓名',job varchar(10) COMMENT '雇員職位',mgr int unsigned COMMENT '雇員對應的領導的編號',hiredate date COMMENT '雇員的雇傭日期',sal decimal(7,2) COMMENT '雇員的基本工資',comm decimal(7,2) COMMENT '獎金',deptno int unsigned COMMENT '所在部門',primary key(empno),foreign key(deptno) references dept(deptno) ) COMMENT='雇員表';INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20); INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30); INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30); INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,'1981-4-2',2975,NULL,20); INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,'1981-9-28',1250,1400,30); INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30); INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,'1981-6-9',2450,NULL,10); INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,'87-7-13',3000,NULL,20); INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10); INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,'1981-9-8',1500,0,30); INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,'87-7-13',1100,NULL,20); INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,'1981-12-3',950,NULL,30); INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20); INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10);create table salgrade(grade int unsigned COMMENT '工資等級',losal int unsigned COMMENT '此等級的最低工資',hisal int unsigned COMMENT '此等級的最高工資' ) COMMENT='工資等級表';INSERT INTO salgrade VALUES (1,700,1200); INSERT INTO salgrade VALUES (2,1201,1400); INSERT INTO salgrade VALUES (3,1401,2000); INSERT INTO salgrade VALUES (4,2001,3000); INSERT INTO salgrade VALUES (5,3001,9999);create table bonus(ename varchar(10) COMMENT '雇員姓名',job varchar(9) COMMENT '雇員職位',sal decimal(7,2) COMMENT '雇員工資',comm decimal(7,2) COMMENT '雇員資金' ) COMMENT='獎金表';-- 3 SQL Server版本 IF EXISTS(Select 1 From Sysobjects Where Name='emp') --查詢表名costSeparateConfig是否存在 DROP table emp; --存在則刪除 IF EXISTS(Select 1 From Sysobjects Where Name='dept') DROP table dept; IF EXISTS(Select 1 From Sysobjects Where Name='bonus') DROP table bonus ; IF EXISTS(Select 1 From Sysobjects Where Name='salgrade') DROP table salgrade; GO create table dept(deptno int IDENTITY(1,1) NOT NULL,dname varchar(15),loc varchar(50), primary key(deptno) );EXECUTE sp_addextendedproperty N'MS_Description', N'部門表', N'user', N'dbo', N'table', N'dept', NULL, NULL EXECUTE sp_addextendedproperty N'MS_Description', N'部門編號', N'user', N'dbo', N'table', N'dept', N'column', N'deptno' EXECUTE sp_addextendedproperty N'MS_Description', N'部門名稱', N'user', N'dbo', N'table', N'dept', N'column', N'dname' EXECUTE sp_addextendedproperty N'MS_Description', N'部門所在位置', N'user', N'dbo', N'table', N'dept', N'column', N'loc'-- set IDENTITY_INSERT dept on SET IDENTITY_INSERT dbo.dept ON; INSERT INTO dept(deptno,dname,loc) VALUES (10,'ACCOUNTING','NEW YORK'); INSERT INTO dept(deptno,dname,loc) VALUES (20,'RESEARCH','DALLAS'); INSERT INTO dept(deptno,dname,loc) VALUES (30,'SALES','CHICAGO'); INSERT INTO dept(deptno,dname,loc) VALUES (40,'OPERATIONS','BOSTON'); set IDENTITY_INSERT dbo.dept OFF;create table emp(empno int IDENTITY(1,1) NOT NULL,ename varchar(15),job varchar(10),mgr int ,hiredate date,sal decimal(7,2),comm decimal(7,2),deptno int,primary key(empno),foreign key(deptno) references dept(deptno) );EXECUTE sp_addextendedproperty N'MS_Description', N'雇員表', N'user', N'dbo', N'table', N'emp', NULL, NULL EXECUTE sp_addextendedproperty N'MS_Description', N'雇員編號', N'user', N'dbo', N'table', N'emp', N'column', N'empno' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員名稱', N'user', N'dbo', N'table', N'emp', N'column', N'ename' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員職位', N'user', N'dbo', N'table', N'emp', N'column', N'job' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員對應的領導的編號', N'user', N'dbo', N'table', N'emp', N'column', N'mgr' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員的雇傭日期', N'user', N'dbo', N'table', N'emp', N'column', N'hiredate' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員的基本工資', N'user', N'dbo', N'table', N'emp', N'column', N'sal' EXECUTE sp_addextendedproperty N'MS_Description', N'獎金', N'user', N'dbo', N'table', N'emp', N'column', N'comm' EXECUTE sp_addextendedproperty N'MS_Description', N'所在部門', N'user', N'dbo', N'table', N'emp', N'column', N'deptno'set IDENTITY_INSERT emp on; INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7566,'JONES','MANAGER',7839,'1981-4-2',2975,NULL,20); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7654,'MARTIN','SALESMAN',7698,'1981-9-28',1250,1400,30); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7782,'CLARK','MANAGER',7839,'1981-6-9',2450,NULL,10); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7788,'SCOTT','ANALYST',7566,'1987-7-13',3000,NULL,20); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7844,'TURNER','SALESMAN',7698,'1981-9-8',1500,0,30); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7876,'ADAMS','CLERK',7788,'1987-7-13',1100,NULL,20); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7900,'JAMES','CLERK',7698,'1981-12-3',950,NULL,30); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20); INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10); SET IDENTITY_INSERT emp OFF;create table salgrade(grade int,losal int,hisal int ) ;EXECUTE sp_addextendedproperty N'MS_Description', N'工資等級表', N'user', N'dbo', N'table', N'salgrade', NULL, NULL EXECUTE sp_addextendedproperty N'MS_Description', N'工資等級', N'user', N'dbo', N'table', N'salgrade', N'column', N'grade' EXECUTE sp_addextendedproperty N'MS_Description', N'此等級的最低工資', N'user', N'dbo', N'table', N'salgrade', N'column', N'losal' EXECUTE sp_addextendedproperty N'MS_Description', N'此等級的最高工資', N'user', N'dbo', N'table', N'salgrade', N'column', N'hisal'INSERT INTO salgrade VALUES (1,700,1200); INSERT INTO salgrade VALUES (2,1201,1400); INSERT INTO salgrade VALUES (3,1401,2000); INSERT INTO salgrade VALUES (4,2001,3000); INSERT INTO salgrade VALUES (5,3001,9999);create table bonus(ename varchar(10),job varchar(9),sal decimal(7,2),comm decimal(7,2) );EXECUTE sp_addextendedproperty N'MS_Description', N'獎金表', N'user', N'dbo', N'table', N'bonus', NULL, NULL EXECUTE sp_addextendedproperty N'MS_Description', N'雇員姓名', N'user', N'dbo', N'table', N'bonus', N'column', N'ename' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員職位', N'user', N'dbo', N'table', N'bonus', N'column', N'job' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員工資', N'user', N'dbo', N'table', N'bonus', N'column', N'sal' EXECUTE sp_addextendedproperty N'MS_Description', N'雇員資金', N'user', N'dbo', N'table', N'bonus', N'column', N'comm' ?員工關系表
7.1.2 學生選課關系表
數據后期補充
7.1.3 供應商關系表
數據后期補充
7.2.1 從表中查詢所有行和列
需求:檢索表里所有行的數據。
解決方法:通過SQL的關鍵字*來匹配到所有行和列,結合SELECT FROM 即可滿足需求。
Oracle、Sql server、Mysql:
SELECT * FROM emp; ?等價于:
SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno FROM emp;執行結果:
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
| 7369 | SMITH | CLERK | 7902 | 1980/12/17 0:00:00 | 800.00 | 20 | |
| 7499 | ALLEN | SALESMAN | 7698 | 1981/2/20 0:00:00 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981/2/22 0:00:00 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981/4/2 0:00:00 | 2975.00 | 20 | |
| 7654 | MARTIN | SALESMAN | 7698 | 1981/9/28 0:00:00 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981/5/1 0:00:00 | 2850.00 | 30 | |
| 7782 | CLARK | MANAGER | 7839 | 1981/6/9 0:00:00 | 2450.00 | 10 | |
| 7788 | SCOTT | ANALYST | 7566 | 1987/7/13 0:00:00 | 3000.00 | 20 | |
| 7839 | KING | PRESIDENT | 1981/11/17 0:00:00 | 5000.00 | 10 | ||
| 7844 | TURNER | SALESMAN | 7698 | 1981/9/8 0:00:00 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987/7/13 0:00:00 | 1100.00 | 20 | |
| 7900 | JAMES | CLERK | 7698 | 1981/12/3 0:00:00 | 950.00 | 30 | |
| 7902 | FORD | ANALYST | 7566 | 1981/12/3 0:00:00 | 3000.00 | 20 | |
| 7934 | MILLER | CLERK | 7782 | 1982/1/23 0:00:00 | 1300.00 | 10 |
?
7.2.2 從表中查詢部分行
需求:查詢雇員表emp里員工號是7782的員工的詳細信息。
解決方法:先找出emp表的員工號的字段名,再結合SELECT FROM WHERE來實現。其中這里通過where關鍵字來限制檢索的行。
Oracle、Sql server、Mysql:
SELECT * FROM emp WHERE empno = 7782;執行結果:
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
| 7782 | CLARK | MANAGER | 7839 | 1981/6/9 0:00:00 | 2450.00 | 10 |
?
7.2.3 查詢滿足某個條件行
需求:查詢雇員表emp中所有的部門號等于10的行。
解決方法:先找出emp表的部門號的字段名,再結合SELECT FROM WHERE來實現。其中的WHERE即是在加過濾條件,多部門表進行篩選,只取部門號為10的數據。
Oracle、Sql server、Mysql:
SELECT * FROM emp WHERE deptno = 10;執行結果:
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
| 7782 | CLARK | MANAGER | 7839 | 1981/6/9 0:00:00 | 2450.00 | 10 | |
| 7839 | KING | PRESIDENT | 1981/11/17 0:00:00 | 5000.00 | 10 | ||
| 7934 | MILLER | CLERK | 7782 | 1982/1/23 0:00:00 | 1300.00 | 10 |
注:
1 這里字段的判斷支持諸如不等于(“<>”)、等于(“=”),大于(“>”)、小于(“<”) 、,
大于等于(“>=”)、小于等于(“<=”),不等(“!”)等關系比較符。
2 上述的比較符對表字段的類型有要求,一般適用于數值類型。
3 當然我們也可以在where之后結合其它條件再過濾,后面會有案例。
7.2.4 從表中查詢部分列
需求:查詢雇員表emp中所有的員工編號、員工名稱、職位情況。
解決方法:先找出emp表的工編號、員工名稱、職位對應的字段名,再結合SELECT FROM 即可滿足需求。
Oracle、Sql server、Mysql:
SELECT empno,ename,job FROM emp; ?執行結果:
| empno | ename | job |
| 7369 | SMITH | CLERK |
| 7499 | ALLEN | SALESMAN |
| 7521 | WARD | SALESMAN |
| 7566 | JONES | MANAGER |
| 7654 | MARTIN | SALESMAN |
| 7698 | BLAKE | MANAGER |
| 7782 | CLARK | MANAGER |
| 7788 | SCOTT | ANALYST |
| 7839 | KING | PRESIDENT |
| 7844 | TURNER | SALESMAN |
| 7876 | ADAMS | CLERK |
| 7900 | JAMES | CLERK |
| 7902 | FORD | ANALYST |
| 7934 | MILLER | CLERK |
7.2.5 給字段取個有意義的名字
需求:查詢雇員表emp里部門編號是10的員工編號、員工名稱、職位情況,并給員工編號起個別名“員工號”,給員工名稱起個別名“員工名”,給職位起個名字“職位名”。
解決方法:先找出emp表的工編號、員工名稱、職位對應的字段名,再結合SELECT column as “別名”FROM table的方式解決。
Oracle、Sql server、Mysql:
SELECT empno as "員工號",ename as"員工名",job as"職位名" FROM emp WHERE deptno =10;也可以省略掉as寫成如下的:
SELECT empno "員工號",ename "員工名",job "職位名" FROM emp WHERE deptno =10;執行結果:
| 員工號 | 員工名 | 職位名 |
| 7782 | CLARK | MANAGER |
| 7839 | KING | PRESIDENT |
| 7934 | MILLER | CLERK |
注: 這里為了演示,將字段名起個別名是中文, 一般情況下不會這么做。因為表名或者字段是用英文定義的,如果名字比較長了或者不好理解,可以起個別名代替。比如有個表叫employee,可以起個別名emp,這個表里有個字段叫salary,可以起個別名叫sal。
一般我們這么寫:
SELECT empno as id,sal salary,comm commission FROM emp WHERE deptno = 10;7.2.6 結合where使用別名
需求:查詢雇員表emp里工資大于3000的員工編號、員工名稱、職位、工資情況,并以工資的別名“salary”進行過濾。
解決方法:先找出emp表的工編號、員工名稱、職位、工資對應的字段名分別為empno、ename、job、sal,結合SELECT column as “別名”FROM table的方式給字段sal起個別名salary,這里需要用個只是,內斂表,即將查詢的結果集用“()”包裹起來起個別名,也可以理解成用個虛擬的表。再在這個內斂表的基礎上過濾salary大于3000的記錄即可。
Oracle、Sql server、Mysql:
SELECT * FROM ( SELECT empno,ename,job,sal salary FROM emp )X WHERE salary>3000執行結果:
| empno | ename | job | salary |
| 7839 | KING | PRESIDENT | 5000.00 |
7.2.7 拼接列的值
需求:查詢雇員表emp里部門編號是10員工信息,以員工名稱“’job title is”職位的形式輸出。示例:KING’s job title is PRESIDENT
解決方法:首先定位到emp表和涉及到字段員工名稱、職位,再考慮兩列的拼接,選擇字符串函數或則“+”完成,最后加上where條件過濾部門編號等于10。這里不同的數據庫實現方法不同。以下分別來講。
Mysql:
SELECT concat(ename,"'s job title is:",job) as EnameConn FROM emp WHERE deptno =10;Sql server:
SELECT ename+'''s job title is:'+job as EnameConn FROM empOracle:
SELECT ename||'''s job title is:'||job as EnameConn FROM emp執行結果:
| EnameConn |
| CLARK's job title is:MANAGER |
| KING's job title is:PRESIDENT |
| MILLER's job title is:CLERK |
7.2.8 查詢語句里執行條件判斷
需求:查詢雇員表emp里的員工名稱、工資、工資分類狀態。這里的工資分類狀態按照以下規則顯示:如果工資小于等于2000則顯示UNDERPAID(即報酬比較低的),如果工資大于4000時顯示OVERPAID(即報酬較高),其它情況顯示NORMAL(正常水平)。
解決方法:首先定位到emp表和涉及到字段員工名稱、工資,再考慮考慮到工資狀態是個計算出來的列,所以先梳理工資分類狀態這個“列”的邏輯,跟表里的工資字段有關,這里是做 if else判斷,注意到純SQL里沒有if else,但有case when,所以我們選取這個關鍵字。case when 條件1 then value1 case when 條件2 then value2 else value3 end as 別名。
Mysql、SQL server、Oracle:
SELECT ENAME,SAL, CASE WHEN SAL <=2000 THEN 'UNDERPAID'WHEN SAL > 2000 THEN 'OVERPAID' ELSE 'NORMAL' END AS STATUS FROM emp執行結果:
| ENAME | SAL | STATUS |
| SMITH | 800.00 | UNDERPAID |
| ALLEN | 1600.00 | UNDERPAID |
| WARD | 1250.00 | UNDERPAID |
| JONES | 2975.00 | OVERPAID |
| MARTIN | 1250.00 | UNDERPAID |
| BLAKE | 2850.00 | OVERPAID |
| CLARK | 2450.00 | OVERPAID |
| SCOTT | 3000.00 | OVERPAID |
| KING | 5000.00 | OVERPAID |
| TURNER | 1500.00 | UNDERPAID |
| ADAMS | 1100.00 | UNDERPAID |
| JAMES | 950.00 | UNDERPAID |
| FORD | 3000.00 | OVERPAID |
| MILLER | 1300.00 | UNDERPAID |
注:case when還可以如下方式編寫:
select ename,sal,job, case job when 'CLERK' then '小職員'when 'SALESMAN' then '銷售員'when 'MANAGER' then '經理'when 'ANALYST' then '分析師'when 'PRESIDENT' then '董事長'else "其它" end as jobtitle from emp ?執行結果:
| ename | sal | job | jobtitle |
| SMITH | 800.00 | CLERK | 小職員 |
| ALLEN | 1600.00 | SALESMAN | 銷售員 |
| WARD | 1250.00 | SALESMAN | 銷售員 |
| JONES | 2975.00 | MANAGER | 經理 |
| MARTIN | 1250.00 | SALESMAN | 銷售員 |
| BLAKE | 2850.00 | MANAGER | 經理 |
| CLARK | 2450.00 | MANAGER | 經理 |
| SCOTT | 3000.00 | ANALYST | 分析師 |
| KING | 5000.00 | PRESIDENT | 董事長 |
| TURNER | 1500.00 | SALESMAN | 銷售員 |
| ADAMS | 1100.00 | CLERK | 小職員 |
| JAMES | 950.00 | CLERK | 小職員 |
| FORD | 3000.00 | ANALYST | 分析師 |
| MILLER | 小職員 |
?這種case 字段A when value1的方式適合字段有可窮舉的情況,而case when 字段條件A則比這種更靈活。
7.2.9 返回的字段在某個范圍內的數據
需求:查詢雇員表emp里部門編號在10和30的部門編號、雇員名稱、職位名稱。
解決方法:使用數據庫里IN關鍵字來限制員工表里的deptno。
Mysql、Sql server、Oracle:
SELECT ename,job FROM emp WHERE deptno IN (20,30)執行結果:
| ename | job | deptno |
| SMITH | CLERK | 20 |
| ALLEN | SALESMAN | 30 |
| WARD | SALESMAN | 30 |
| JONES | MANAGER | 20 |
| MARTIN | SALESMAN | 30 |
| BLAKE | MANAGER | 30 |
| SCOTT | ANALYST | 20 |
| TURNER | SALESMAN | 30 |
| ADAMS | CLERK | 20 |
| JAMES | CLERK | 30 |
| FORD | ANALYST | 20 |
7.2.10 通過多條件組合返回數據
需求:查詢雇員表emp里部門編號在10和30且職位是經理“MANAGER”的的雇員名稱、職位名稱。
解決方法:使用數據庫里IN關鍵字來限制員工表里的deptno。
Mysql、Sql server、Oracle:
SELECT ename,job FROM emp WHERE deptno IN (20,30) AND job='MANAGER'執行結果:
| ename | job |
| JONES | MANAGER |
| BLAKE | MANAGER |
注: 這里字段的邏輯條件里常用的有and、or,注意這里的優先級,如果想改變優先級,可以通過“()”來改變。
7.2.11 限制返回的行數
需求:查詢5條雇員表emp里的雇員信息。
解決方法:使用數據庫里內置的限制行數返回的函數來解決。
Mysql:
SELECT * FROM emp limit 5;Sql server:
SELECT TOP 5 * FROM emp;Oracle:
SELECT * FROM emp WHERE rownum <=5執行結果:
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
| 7369 | SMITH | CLERK | 7902 | 1980/12/17 0:00:00 | 800.00 | 20 | |
| 7499 | ALLEN | SALESMAN | 7698 | 1981/2/20 0:00:00 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981/2/22 0:00:00 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981/4/2 0:00:00 | 2975.00 | 20 | |
| 7654 | MARTIN | SALESMAN | 7698 | 1981/9/28 0:00:00 | 1250.00 | 1400.00 | 30 |
7.2.12 從表中隨機返回N條記錄
需求:從雇員表emp里隨機查詢5條雇員的名稱和工資信息。
解決方法:使用數據庫里內置的限制行數函數結合隨機函數來解決。
Mysql:
SELECT ename,sal FROM emp order by rand() limit 5;Sql server:
SELECT TOP 5 ename,sal FROM emp ORDER BY NEWID()注: newid是SQL Server里的內置函數,因為newid()返回的是uniqueidentifier類型的唯一值,而且每次生成的值都不一樣,所以能達到隨機的效果。
Oracle:
SELECT * FROM ( SELECT ename,sal FROM emp ORDER BY Dbms_Random.value() ) WHERE rownum <=5注: dbms_random是一個可以生成隨機數值或者字符串的程序包。這個包有initialize()、seed()、terminate()、value()、normal()、random()、string()等幾個函數,但返回隨機值的函數value()是最常用的。
你可以直接訪問這個隨機數字的函數,它返回個0到1之間的一個小數。
SELECT Dbms_Random.value() AS RAND_VALUE FROM DUAL;執行結果:
| RAND_VALUE |
| 0.151493981662762 |
如果想生成1-100之間的隨機數,你可以這么做:
SELECT TRUNC(Dbms_Random.value()*100)AS RAND_VALUE FROM DUAL;執行結果:
| RAND_VALUE |
| 42 |
7.2.13 從表中查詢空值
需求:從雇員表emp里查詢所有獎金為空的員工名稱、工資信息和獎金信息。
解決方法:首先找到該段邏輯的涉及到的表名和字段名,emp表,字段ename,sal,comm,使用IS NULL關鍵字來來解決,這里的NULL是描述數據的特殊值,即不明確該值是什么,區別于空字符串“''”,空字符串不等于NULL。
Mysql、Sql server、Oracle:
SELECT ename,sal,comm FROM emp WHERE comm IS NULL執行結果:
| ename | sal | comm |
| SMITH | 800.00 | |
| JONES | 2975.00 | |
| BLAKE | 2850.00 | |
| CLARK | 2450.00 | |
| SCOTT | 3000.00 | |
| KING | 5000.00 | |
| ADAMS | 1100.00 | |
| JAMES | 950.00 | |
| FORD | 3000.00 | |
| MILLER | 1300.00 |
7.2.14 返回不重復的記錄
需求:從雇員表emp里查詢所有不重復的職位信息。
解決方法:這里用到SQL的DISTINCT關鍵字,即對重復的記錄進行去重。
Mysql、Sql server、Oracle:
SELECT DISTINCT JOB FROM emp執行結果:
| JOB |
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
7.2.15 將空值轉成其它值
需求:從雇員表emp里查詢所有獎金為空的員工名稱、工資信息和獎金信息。這里如果獎金為空則轉為0。
解決方法:首先找到該段邏輯的涉及到的表名和字段名,emp表,字段ename,sal,comm,使用IS NULL關鍵字來來解決,如果comm為null則轉為0 如果不是null則返回本身。
Mysql、Sql Server、Oracle:
SELECT ename,sal,case WHEN comm IS NULL THEN 0ELSE commEND AS comm FROM emp WHERE comm IS NULL執行結果:
| ename | sal | comm |
| SMITH | 800.00 | 0 |
| JONES | 2975.00 | 0 |
| BLAKE | 2850.00 | 0 |
| CLARK | 2450.00 | 0 |
| SCOTT | 3000.00 | 0 |
| KING | 5000.00 | 0 |
| ADAMS | 1100.00 | 0 |
| JAMES | 950.00 | 0 |
| FORD | 3000.00 | 0 |
| MILLER | 1300.00 | 0 |
或者用下面的方法,這里每個數據庫里的函數名各不同:
Mysql:
SELECT ename,sal, ROUND(IFNULL(comm,0))as comm FROM emp WHERE comm IS NULLSql Server:
SELECT ename,sal, ISNULL(comm,0)AS comm FROM emp WHERE comm IS NULLOracle:
SELECT ename,sal,NVL(comm,0) AS comm FROM emp WHERE comm IS NULL7.2.16 按照某個模式搜索
需求:從雇員表emp里查詢部門號是10或者20的員工名稱,職位信息,他們要么員工名稱里含有“I”要么他們的職位以“ER”結尾。
解決方法:這里用到SQL的關鍵字“%”,注意如果字段里以“%匹配關鍵字%”則會匹配“匹配關鍵字”在字段里的任何地方,同理如果是“匹配關鍵字%”則是以“匹配關鍵字”開頭來匹配字段,而“%匹配關鍵字”則是匹配以“匹配關鍵字”結尾來匹配字段。
Mysql、Sqlserver、Oracle:
SELECT ename,job FROM emp WHERE deptno IN(10,20) AND (ename LIKE '%I%' OR job LIKE '%ER')執行結果:
| ename | job |
| SMITH | CLERK |
| JONES | MANAGER |
| CLARK | MANAGER |
| KING | PRESIDENT |
| MILLER | CLERK |
7.2.17 按照指定的次序返回查詢結果
需求:從雇員表emp里查詢所有的員工名稱,職位,獎金信息,這里要求獎金不為空的排在前面。
解決方法:這里用到SQL的關鍵字 ORDER BY 以及ASC和DESC,order by是指定以某個或者某些字段排序,asc是指代以字母順序排列而desc則是以字母降序排列。
Mysql、SqlServer:
SELECT ename,job,comm FROM emp order by comm執行結果:
| ename | job | comm |
| SMITH | CLERK | |
| JONES | MANAGER | |
| BLAKE | MANAGER | |
| CLARK | MANAGER | |
| SCOTT | ANALYST | |
| KING | PRESIDENT | |
| ADAMS | CLERK | |
| JAMES | CLERK | |
| FORD | ANALYST | |
| MILLER | CLERK | |
| TURNER | SALESMAN | 0.00 |
| ALLEN | SALESMAN | 300.00 |
| WARD | SALESMAN | 500.00 |
| MARTIN | SALESMAN | 1400.00 |
Oracle:
SELECT ename,job,comm FROM emp order by comm執行結果:
| ENAME | JOB | COMM |
| TURNER | SALESMAN | 0.00 |
| ALLEN | SALESMAN | 300.00 |
| WARD | SALESMAN | 500.00 |
| MARTIN | SALESMAN | 1400.00 |
| SCOTT | ANALYST | |
| KING | PRESIDENT | |
| ADAMS | CLERK | |
| JAMES | CLERK | |
| FORD | ANALYST | |
| MILLER | CLERK | |
| BLAKE | MANAGER | |
| JONES | MANAGER | |
| SMITH | CLERK | |
| CLARK | MANAGER |
注:因為Sql Server和Mysql默認以NULL的排在前面,而Oralce則默認以NULL的排在后面。
7.2.18 按照多個字段排序查詢結果
需求:從雇員表emp里查詢所有的部門編號,員工名稱,職位,工資信息,這里要求先以部門編號排序再以工資從高到低排序顯示。
解決方法:這里用到SQL的關鍵字 ORDER BY 以及ASC和DESC,order by是指定以字段deptno字符排序,以工資降序排列。
Mysql、Sql server、Oracle:
SELECT deptno,ename,job,sal FROM emp order by deptno,comm desc執行結果:
| deptno | ename | job | sal |
| 10 | CLARK | MANAGER | 2450.00 |
| 10 | KING | PRESIDENT | 5000.00 |
| 10 | MILLER | CLERK | 1300.00 |
| 20 | SMITH | CLERK | 800.00 |
| 20 | JONES | MANAGER | 2975.00 |
| 20 | SCOTT | ANALYST | 3000.00 |
| 20 | ADAMS | CLERK | 1100.00 |
| 20 | FORD | ANALYST | 3000.00 |
| 30 | MARTIN | SALESMAN | 1250.00 |
| 30 | WARD | SALESMAN | 1250.00 |
| 30 | ALLEN | SALESMAN | 1600.00 |
| 30 | TURNER | SALESMAN | 1500.00 |
| 30 | BLAKE | MANAGER | 2850.00 |
| 30 | JAMES | CLERK | 950.00 |
?
7.2.19 按照字符串對結果排序
需求:從雇員表emp里查詢所有的部門編號,員工名稱,職位,工資信息,職位的后兩位信息,這里要求截取job字段里的最后兩位來排序。
解決方法:這里用到SQL的字符串截取函數再結合order by來對結果進行排序。
Mysql:
SELECT deptno,ename,job,sal,substring(job,length(job)-1) AS last2word FROM emp order by last2wordOracle:
SELECT deptno,ename,job,sal,substr(job,length(job)-1) AS last2word FROM emp order by last2word ??Sql serer: SELECT deptno,ename,job,sal,substring(job,len(job)-1,2) AS last2word FROM emp order by last2word執行結果:
| deptno | ename | job | sal | last2word |
| 30 | ALLEN | SALESMAN | 1600.00 | AN |
| 30 | WARD | SALESMAN | 1250.00 | AN |
| 30 | MARTIN | SALESMAN | 1250.00 | AN |
| 30 | TURNER | SALESMAN | 1500.00 | AN |
| 20 | JONES | MANAGER | 2975.00 | ER |
| 30 | BLAKE | MANAGER | 2850.00 | ER |
| 10 | CLARK | MANAGER | 2450.00 | ER |
| 10 | KING | PRESIDENT | 5000.00 | NT |
| 20 | SMITH | CLERK | 800.00 | RK |
| 20 | ADAMS | CLERK | 1100.00 | RK |
| 30 | JAMES | CLERK | 950.00 | RK |
| 10 | MILLER | CLERK | 1300.00 | RK |
| 20 | SCOTT | ANALYST | 3000.00 | ST |
| 20 | FORD | ANALYST | 3000.00 | ST |
7.2.20 按照字符串數字組合的排序
需求:假設我們從雇員表emp里創建個視圖,這里僅有一個字段,該字段叫data由員工名稱和部門號拼接而成,我們想實現一個查詢可以按照原來的部門編號逆序排序篩選出數據。
解決方法:這里沒有真正創建視圖,因為用戶權限問題,而是建了個表叫做tmp_v。字段拼接生成新字段見上面章節。這里要通過數據庫里的translate和repacle結合來實現這個功能。
注:SQL Server、Mysql里參照網上實現了translate函數,詳細見下。
Oracle:
create table tmp_v as SELECT ename||' '|| deptno as data from emp;SELECT data,replace(translate(data,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','@@@@@@@@@@@@@@@@@@@@@@@@@@'),'@','') as deptno FROM tmp_v order by replace(translate(data,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','@@@@@@@@@@@@@@@@@@@@@@@@@@'),'@','') desc執行結果:
| DATA | DEPTNO |
| BLAKE 30 | 30 |
| TURNER 30 | 30 |
| ALLEN 30 | 30 |
| MARTIN 30 | 30 |
| WARD 30 | 30 |
| JAMES 30 | 30 |
| SCOTT 20 | 20 |
| JONES 20 | 20 |
| SMITH 20 | 20 |
| ADAMS 20 | 20 |
| FORD 20 | 20 |
| KING 10 | 10 |
| MILLER 10 | 10 |
?注:
1 因為我們的ename里的名字都是大寫的,所以這里translate函數里的第二個參數都是大寫的,如果data里是小寫的這里自然是小寫。
2 translate函數有三個參數,第一個一般是字段名或則字符串的值,第二個是要匹配的字符組合,第三個是要裝換成的字符。
3 replace函數一般有三個參數,第一個一般是字段名或則字符串的值,第二個要替換的字段,第三個是要替換成的值。
SQL Server:
可以在SQLServer里實現個自定義個函數叫translate, 參考至http://blog.sina.com.cn/s/blog_95cfa64601018akj.html具體實現見下:
SET ANSI_NULLSON GO SET QUOTED_IDENTIFIERON GO CREATE FUNCTION [dbo].[translate](@string VARCHAR(MAX),@from_str VARCHAR(MAX),@to_str VARCHAR(MAX) ) RETURNS VARCHAR(MAX) AS BEGIN-- 返回將(所有出現的)from_str中的每個字符替換為to_str中的相應字符以后的string。-- TRANSLATE是 REPLACE所提供的功能的一個超集。-- 如果 from_str比 to_str 長,那么在 from_str 中而不在 to_str 中的額外字符將從 string 中被刪除,因為它們沒有相應的替換字符。-- to_str不能為空。-- Oracle將空字符串解釋為 NULL,并且如果TRANSLATE 中的任何參數為NULL,那么結果也是 NULL。IF @string IS NULL OR @from_strISNULLOR @to_strISNULLBEGINRETURN NULL;END;-- 源長度與目標長度DECLARE @FromLen INT, @ToLen INT;SET @FromLen = LEN(@from_str);SET @ToLen = LEN(@to_str);-- 準備用于返回的數值.DECLARE @resultVal VARCHAR(MAX);SET @resultVal =@string;-- 用于存儲 本次需要替換的字符信息.DECLARE @thisTimeReplace CHAR(1);-- 從后向前依次替換.WHILE @FromLen > 0BEGIN-- 取得本次即將要替換的字符.SET @thisTimeReplace =SUBSTRING(@from_str, @FromLen, 1);IF CHARINDEX(@thisTimeReplace,@from_str)<@FromLenBEGIN-- 假如當前這個要替換的字符,在前面還有,那么這里就不替換了-- 原因,為了支持-- SELECT TRANSLATE('2KRW229','1234567890' || '2KRW229', '1234567890')-- 這樣的效果.-- 向前處理上一個/*補充說明:1 理論上TRANSLATE函數的@from_str參數和@to_str參數的長度要一致,即一一映射。比如@from_str='0123',@to_str='abcd'2 該步驟旨在找到在@from_str參數里要替換的的字符重復指定了,比如'0123XYZ23',這里23是重復指定了,對于重復指定的要舍棄所以需要在該步時需要將@FromLen鎖定到字符Z的位置即7*/SET @FromLen =@FromLen - 1;CONTINUE;ENDIF @FromLen >@ToLenBEGIN--from_str 比 to_str長,那么在 from_str 中而不在 to_str 中的額外字符將從 string 中被刪除,因為它們沒有相應的替換字符。SET @resultVal =REPLACE(@resultVal,SUBSTRING(@from_str, @FromLen, 1),'');ENDELSEBEGIN-- from_str中的每個字符替換為to_str中的相應字符以后的string--SELECT dbo.TRANSLATE('2KRW229', '12345678902KRS229','12345678902')這里用S替換時其實無效SET @resultVal =REPLACE(@resultVal, @thisTimeReplace,SUBSTRING(@to_str, @FromLen, 1));END;-- 處理完當前字符后,向前處理上一個.SET @FromLen =@FromLen - 1;END;-- 依次處理完畢后,返回結果.RETURN @resultVal;ENDcreate view tmp_v AS SELECT ename+' '+cast(deptnoasvarchar)as data from emp;SELECT data,replace(dbo.translate(data,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','@@@@@@@@@@@@@@@@@@@@@@@@@@'),'@','') as deptno FROM tmp_v order by replace(dbo.translate(data,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','@@@@@@@@@@@@@@@@@@@@@@@@@@'),'@','')desc ?執行結果:
| DATA | DEPTNO |
| ALLEN 30 | 30 |
| WARD 30 | 30 |
| MARTIN 30 | 30 |
| BLAKE 30 | 30 |
| TURNER 30 | 30 |
| JAMES 30 | 30 |
| FORD 20 | 20 |
| SMITH 20 | 20 |
| ADAMS 20 | 20 |
| SCOTT 20 | 20 |
| JONES 20 | 20 |
| CLARK 10 | 10 |
| KING 10 | 10 |
注: SQL Server 2017里已經有translate函數,見如下示例:
DECLARE @v VARCHAR(100)?
SET @v = '123#456*789!/0'?
SELECT REPLACE(TRIM(TRANSLATE(@v,'#*!/','??? ')),' ','') AS transDemo
| transDemo |
| 1234567890 |
Mysql:
可以在Mysql里實現個自定義個函數叫translate,具體實現見下:
DROP FUNCTION IF EXISTS shenl.translate; CREATE FUNCTION shenl.`translate`( stringToTranslate VARCHAR(256), from_str VARCHAR(256), to_str VARCHAR(256)) RETURNSvarchar(256)CHARSET utf8BEGINDECLARE resultVal VARCHAR(256); DECLARE FromLen INT; DECLARE ToLen INT; DECLARE thisTimeReplace VARCHAR(1); SET FromLen = LENGTH(from_str); SET ToLen = LENGTH(to_str); SET resultVal = stringToTranslate;IF stringToTranslate IS NULL OR from_strISNULLOR to_strISNULLTHENRETURN NULL; END IF;loop_label: LOOP#因為是從后往前替換,所以FromLen=0時循環要結束了。IF FromLen<=0THENLEAVE loop_label;END IF;#from_str里從后往前每次取1個字符SET thisTimeReplace = SUBSTRING(from_str, FromLen, 1);#如果在from_str字符串里重復指定了要替換的字符,則舍棄。即如果from_str的值是1234567890fat29,則29是要舍棄掉的。#即FromLen要鎖定到13IF INSTR(from_str,thisTimeReplace)< FromLen THENSET FromLen = FromLen - 1;ITERATE loop_label;ELSE#如果from_str的長度大于ToLen則以ToLen的長度為標準,此時from_str里多提供的字符會被替換為''IF FromLen > ToLen THEN SET resultVal = REPLACE(resultVal, SUBSTRING(from_str, FromLen, 1),'');#如果from_str的長度等于ToLen則以ToLen對應的字符替換from_str里多的字符ELSESET resultVal = REPLACE(resultVal, thisTimeReplace, SUBSTRING(to_str, FromLen, 1)); END IF; SET FromLen = FromLen - 1;END IF; END LOOP;RETURN resultVal; END;create view tmp_v AS SELECTCONCAT(ename,' ',deptno)as data from emp;SELECT data,replace(translate(data,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','@@@@@@@@@@@@@@@@@@@@@@@@@@'),'@','') as deptno FROM tmp_v order by replace(translate(data,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','@@@@@@@@@@@@@@@@@@@@@@@@@@'),'@','') desc執行結果:
| data | deptno |
| ALLEN 30 | 30 |
| MARTIN 30 | 30 |
| WARD 30 | 30 |
| BLAKE 30 | 30 |
| JAMES 30 | 30 |
| TURNER 30 | 30 |
| SCOTT 20 | 20 |
| ADAMS 20 | 20 |
| SMITH 20 | 20 |
| JONES 20 | 20 |
| FORD 20 | 20 |
| MILLER 10 | 10 |
| KING 10 | 10 |
| CLARK 10 | 10 |
7.2.21 處理空值的排序
需求:查詢雇員表emp里的員工編號、員工名、獎金信息,這里需要將comm字段為空的排在前面。
解決方法:需要對comm字段進行特殊處理,比如進行轉換,然后再排序,而有的數據庫可以在排序時指定null的順序。如oracle里字段排序時可以指定nulls first或則nulls last
Oracle:
SELECT empno,ename,comm FROM emp ORDER BY comm nulls first執行結果:
| EMPNO | ENAME | COMM |
| 7369 | SMITH | |
| 7782 | CLARK | |
| 7902 | FORD | |
| 7900 | JAMES | |
| 7876 | ADAMS | |
| 7566 | JONES | |
| 7698 | BLAKE | |
| 7934 | MILLER | |
| 7788 | SCOTT | |
| 7839 | KING | |
| 7844 | TURNER | 0.00 |
| 7499 | ALLEN | 300.00 |
| 7521 | WARD | 500.00 |
| 7654 | MARTIN | 1400.00 |
?
Sql Server:
SELECT empno,ename,CASE WHEN comm IS NULL THEN -1 ELSE comm END AS comm FROM emp ORDER BY commMysql:
SELECT empno,ename,CASE WHEN comm IS NULL THEN -1 ELSE comm END AS comm FROM emp ORDER BY comm ?Sqlserver和Mysql的執行結果見下:
| empno | ename | comm |
| 7369 | SMITH | -1.00 |
| 7566 | JONES | -1.00 |
| 7698 | BLAKE | -1.00 |
| 7782 | CLARK | -1.00 |
| 7788 | SCOTT | -1.00 |
| 7839 | KING | -1.00 |
| 7876 | ADAMS | -1.00 |
| 7900 | JAMES | -1.00 |
| 7902 | FORD | -1.00 |
| 7934 | MILLER | -1.00 |
| 7844 | TURNER | 0.00 |
| 7499 | ALLEN | 300.00 |
| 7521 | WARD | 500.00 |
| 7654 | MARTIN | 1400.00 |
7.2.22 根據數據項的值排序
需求:查詢雇員表emp里的員工編號、員工名、工作信息、獎金信息,這里需要對工作是“MANAGER”和“SALESMAN”的按照comm降序排序其他員工按照員工編號降序排列。
解決方法:這里需要在order by后接case when之類的條件判斷以調整排序規則。order by可以跟多個字段,排在前面的規則會被優先應用。
Oracle:
SELECT empno,ename,job,comm FROM emp ORDER BY CASE WHEN job IN ('SALESMAN','MANAGER') THEN comm ELSE empno END DESC執行結果:
| EMPNO | ENAME | JOB | COMM |
| 7782 | CLARK | MANAGER | |
| 7698 | BLAKE | MANAGER | |
| 7566 | JONES | MANAGER | |
| 7934 | MILLER | CLERK | |
| 7902 | FORD | ANALYST | |
| 7900 | JAMES | CLERK | |
| 7876 | ADAMS | CLERK | |
| 7839 | KING | PRESIDENT | |
| 7788 | SCOTT | ANALYST | |
| 7369 | SMITH | CLERK | |
| 7654 | MARTIN | SALESMAN | 1400.00 |
| 7521 | WARD | SALESMAN | 500.00 |
| 7499 | ALLEN | SALESMAN | 300.00 |
| 7844 | TURNER | SALESMAN | 0.00 |
Sql Server、Mysql:
SELECT empno,ename,job,comm FROM emp ORDER BY CASE WHEN job IN('SALESMAN','MANAGER')THEN comm ELSE empno END DESC執行結果:
| empno | ename | job | comm |
| 7934 | MILLER | CLERK | NULL |
| 7902 | FORD | ANALYST | NULL |
| 7900 | JAMES | CLERK | NULL |
| 7876 | ADAMS | CLERK | NULL |
| 7839 | KING | PRESIDENT | NULL |
| 7788 | SCOTT | ANALYST | NULL |
| 7369 | SMITH | CLERK | NULL |
| 7654 | MARTIN | SALESMAN | 1400.00 |
| 7521 | WARD | SALESMAN | 500.00 |
| 7499 | ALLEN | SALESMAN | 300.00 |
| 7844 | TURNER | SALESMAN | 0.00 |
| 7698 | BLAKE | MANAGER | NULL |
| 7782 | CLARK | MANAGER | NULL |
| 7566 | JONES | MANAGER | NULL |
總結
以上是生活随笔為你收集整理的SQL 100+个最佳入门案例实践(覆盖Oralce、SQL Server、Mysql)之基础操作_1_检索数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小茗妈妈一体裤质量过关吗?
- 下一篇: 2020年全国本科专业分类目录及代码(全