說明:
這個分類專欄是我學習SQL的筆記與總結,其內容包含
- Linux下ORACLE的安裝
- 筆記總結(思維導圖、文本)
- 練習題(思路、注意事項)
練習題:
1、選擇部門30中的所有員工;
2、列出所有辦事員(CLERK)的姓名,編號和部門編號;
3、找出獎金高於薪金的員工;
4、找出獎金高於薪金的60%的員工;
5、找出部門10中的所有經理(MANAGER)和部門20中所有的辦事員(CLERK)的詳細資料;
6、找出部門10中所有的經理(MANAGER),部門20中所有辦事員(CLERK),既不是經理又不是辦事員但其薪金大於或等於2000的所有員工的詳細資料;
7、找出收取獎金的員工的不同工作;
8、找出不收取獎金或者收取的獎金低於100的員工;
9、找出各月倒數第三天受僱的所有員工;
10、找出早於十三年前受僱的員工;
如果要求年份,最準確的是使用總月數/13
11、以首字母大寫的方式顯示所有員工的姓名;
12、顯示正好爲5個字符的員工的姓名;
13、顯示不帶有“R”的員工姓名;
14、顯示所有員工姓名的前三個字符;
15、顯示所有員工的姓名,用“a”替換所有的“A”;
17、顯示員工的詳細資料,按姓名排序;
18、顯示員工的姓名和受僱日期,根據其服務年限,將最老的員工排在最前面;
19、顯示所有員工的姓名、工作和薪金,按工作的降序排序,若工作相同則按薪金排序;
20、顯示所有員工姓名、加入公司的年份和月份,按受僱日期所在月排序,若月份相同則將最早年份的員工排在最前面;
21、顯示在一個月爲30天的情況所有員工的日薪金,忽略餘數;
22、找出(任何年份的)2月受聘的所有員工;
23、對於每個員工,顯示其加入公司的天數;
24、顯示姓名字段的任何位置包含“A”的所有員工的姓名;
25、以年月日的方式顯示所有員工的服務年限;
答案:
基本SQL語句練習
以下SQL語句 我只將關鍵字段大寫了
1、選擇部門30中的所有員工;
要查的是所有員工
範圍限定的是部門30
SQL> select * from emp where deptno = 30;
2、列出所有辦事員(CLERK)的姓名,編號和部門編號;
要查的是姓名,編號和部門編號
範圍限定的是辦事員
SQL> select empno,ename,deptno from emp where job='CLERK';
3、找出獎金高於薪金的員工;
要查的是員工
範圍限定的是獎金高於薪金
SQL> select * from emp where comm>sal;
4、找出獎金高於薪金的60%的員工;
要查的是員工
範圍限定的是獎金高於薪金60%
SQL> select * from emp where comm>(sal*0.6);
5、找出部門10中的所有經理(MANAGER)和部門20中所有的辦事員(CLERK)的詳細資料;
要查的是所有資料
範圍限定的是部門10中的所有經理 部門20中所有的辦事員
注意:經理與辦事員字段要大寫,查詢的關係是or
SQL>select * from emp
where (deptno=10 and job='MANAGER') or (deptno=20 and job='CLERK');
6、找出部門10中所有的經理(MANAGER),部門20中所有辦事員(CLERK),既不是經理又不是辦事員但其薪金大於或等於2000的所有員工的詳細資料;
要查的是所有資料,範圍限定的是
部門10中的所有經理
部門20中所有的辦事員
既不是經理又不是辦事員但其薪金大於或等於2000
select * from emp
where (deptno=10 and job='MANAGER')
or (deptno=20 and job='CLERK')
or ((Job!='MANAGER' and job!='CLERK') and sal > =2000);
第三個條件也可以用IN來進行範圍限定 根據題中的要求 使用not in
(job not in ('MANAGER','CLERK') and sal > =2000)
7、找出收取獎金的員工的不同工作;
要查的是工作,
範圍限定的是
收取獎金的員工
SQL> select job from emp where comm is not null;
SQL> select job from emp where not comm is null;
用distinct來刪除重複項
SQL> select distinct job from emp where not comm is null;
8、找出不收取獎金或者收取的獎金低於100的員工;
要查的是員工(詳細資料),
範圍限定的是
不收取獎金 comm爲null
收取的獎金低於100
SQL> select * from emp where comm is null or comm <100;
9、找出各月倒數第三天受僱的所有員工;
要查的是員工(詳細資料),
範圍限定的是
各月倒數第三天受僱
思路:
先取出僱傭日期當月的最後一天 (將其天數取出來) 然後減去2 如果是受僱的天數,那麼就符合條件。
步驟:
- 先取出僱傭日期的day1
- 取出僱傭月份的最後一天day2
- 用大日期減小日期 day2-day1 如果等於2就輸出
select last_day(hiredate) from emp;
SQL> select hiredate,to_char(hiredate,'yyyy-mm-dd'),to_char(hiredate,' dd')day1 from emp;
SQL>select last_day(hiredate),
to_char(last_day(hiredate),'yyyy-mm-dd'),
to_char(last_day(hiredate),' dd')day2
from emp;
爲了計算所以只保留需要的數據字段 day1 day2
select to_char(hiredate,' dd')day1 from emp;
select to_char(last_day(hiredate),' dd')day2 from emp;
最終:
select * from emp where ((to_char(last_day(hiredate),' dd') - to_char(hiredate,' dd')) =2);
檢查:可見第五個人確實是當月的倒數第三天 當月有30天 倒數第三天就是28天
另外一種做法是不用取出來具體的天數 直接用當月最後一天減去2 如果等於hiredate那就符合條件
SQL> SELECT * FROM EMP WHERE LAST_DAY(HIREDATE)-2=HIREDATE;
10、找出早於十三年前受僱的員工;
思路:
首先將受僱的年份取出來,然後用現在的年份受僱的年份 >13 就打印
select to_char(hiredate,'yyyy')year1 from emp;
select to_char(sysdate,' yyyy')year2 from emp;
最終:
select * from emp where (to_char(sysdate,' yyyy') - to_char(hiredate,'yyyy')) > 13 ;
做法2:
SQL> SELECT * FROM EMP WHERE MONTHS_BETWEEN(SYSDATE,HIREDATE)/12>13;
能用函數儘量函數,因爲十分便捷
11、以首字母大寫的方式顯示所有員工的姓名;
SQL> select initcap(ename) from emp;
12、顯示正好爲5個字符的員工的姓名;
SQL> select ename from emp where length(ename)=5;
13、顯示不帶有“R”的員工姓名;
SQL> select ename from emp where ename not like '%R%';
14、顯示所有員工姓名的前三個字符;
按照的是正常的數數,而不是從0開始,從0開始數的是程序員
SQL> select ename,substr(ename,0,3) from emp;
SQL> select ename,substr(ename,1,3) from emp;
15、顯示所有員工的姓名,用“a”替換所有的“A”;
SQL> select replace(ename,'A','a') from emp;
17、顯示員工的詳細資料,按姓名排序;
排序默認用的是升序
SQL> select * from emp order by ename;
SQL> select * from emp order by ename asc;
18、顯示員工的姓名和受僱日期,根據其服務年限,將最老的員工排在最前面;
注意:這裏要按照升序排序,因爲要將時間上小的排在前面(年長的)
SQL> select ename,hiredate from emp order by hiredate asc;
19、顯示所有員工的姓名、工作和薪金,按工作的降序排序,若工作相同則按薪金排序;
SQL> select ename,job,sal from emp order by job desc,sal asc;
20、顯示所有員工姓名、加入公司的年份和月份,按受僱日期所在月排序,若月份相同則將最早年份的員工排在最前面;
由於出現了年份與月份,則應該先進行拆分
月份按照默認的升序排序,最早年份的員工則按照升序
總結:
一旦出現與年份相關的,想要年長的排在前面,那麼就按照升序排序
select ename,to_char(hiredate,'yyyy') year,to_char(hiredate,' mm') month from emp
order by month,year asc;
21、顯示在一個月爲30天的情況所有員工的日薪金,忽略餘數;
要查的是日薪金(忽略餘數)利用別名(日薪金)
範圍限定的是 一個月爲30天
思路:
用sal/30 並忽略餘數,別名替代算出來的日薪金
select ename,trunc(sal/30)day_sal from emp;
22、找出(任何年份的)2月受聘的所有員工;
要查的是員工
範圍限定的是2月受聘的
思路:
利用to_char轉換函數取出月份 減去02 如果等於0 就打印
select ename from emp where ((to_char(hiredate,' mm') -02)=00);
如果需要對所有信息都打印,那麼就用*
select * from emp where ((to_char(hiredate,' mm') -02)=00);
檢查:可見只有這兩個人的受僱月份就是2月
23、對於每個員工,顯示其加入公司的天數;
要查的是員工與僱傭的天數
思路:
用當前日期減去僱傭的日期就是加入的天數
select ename,hiredate,sysdate-hiredate from emp;
24、顯示姓名字段的任何位置包含“A”的所有員工的姓名;
思路:
採用模糊查詢
SQL> select ename from emp where ename like '%A%';
25、以年月日的方式顯示所有員工的服務年限;
第一步:求出每個僱員的僱傭年數:被僱傭的總月數/12=年數
select ename,hiredate,trunc(months_between(sysdate,hiredate)/12)toatl_year from emp;
第二步:求出月數,以上計算之中被忽略的小數點都是月份,所以直接取餘即可。
select ename,hiredate,
trunc(months_between(sysdate,hiredate)/12)toatl_year,
trunc(mod(months_between(sysdate,hiredate),12))total_month
from emp;
第三步:求出天數,最準確的做法是在不超過30天的範圍內計算;
當前時間用sysdate取出,僱傭時期用hiredate取出,可是兩者中間的差距太大,所以肯定的會有誤差,那麼就必須想辦法將hiredate日期提升到與sysdate差距在30天的範圍之內,
有兩個函數;
MONTHS_BETWEEN();求出兩個日期間的月數。
ADD_MONTHS():在一個日期上加入指定的月之後的日期。
如果說hiredate+與今天相距的月數=一個新的日期,而且這個新的日期肯定和sysdate相距不超過30天。
1987入職 +月數(month between(sys date,hiredate )
SQL> select ename,hiredate,
trunc(months_between(sysdate,hiredate)/12)year,
trunc(mod(months_between(sysdate,hiredate),12))month,
trunc(sysdate-add_months(hiredate,months_between(sysdate,hiredate))) day
from emp;