查找最晚入職員工的所有信息
解題步驟:
題目:查詢最晚入職員工的所有信息
目標:查詢員工的所有信息
篩選條件:最晚入職
答案:
1 SELECT 2 *--查詢所有信息就用* 3 FROM 4 employees 5 WHERE 6 hire_date = (--這里是一個子查詢,因為要和hire_date匹配,所以只能是一個值,注意max函數使用規則 7 SELECT 8 MAX(hire_date) 9 FROM 10 employees 11 )
查找入職員工時間排名倒數第三的員工所有信息
解題步驟:
題目:查找入職員工時間排名倒數第三的員工所有信息
目標:查詢員工的所有信息
篩選條件:入職時間到第三
答案:
1 SELECT 2 *--所有信息,用*省事 3 FROM 4 employees 5 where hire_date = ( SELECT DISTINCT--子查詢,注意hire_date是一個值,子查詢的返回值一定要是一個 6 hire_date 7 FROM 8 employees 9 ORDER BY--這里有一個小技巧,倒序排,從第三條取,去一條 10 hire_date DESC 11 limit 2,1--分頁語法要仔細看看,limit m,n=> 從m+1開始取,取n條 12 )
查找各個部門當前(to_date='9999-01-01')領導當前薪水詳情以及其對應部門編號dept_no
解題步驟:
題目:查找各個部門當前(to_date='9999-01-01')領導當前薪水詳情以及其對應部門編號dept_no
目標:查詢領導薪水詳情,對應部門編號
篩選條件:部門表當前時間,隱藏的條件(薪水表當前時間)
答案:
1 SELECT 2 s.*, 3 d.dept_no 4 FROM 5 salaries s--左聯到部門表,薪水表人全,所以做主表比較好,不會出現關聯出空的情況 6 LEFT JOIN dept_manager d ON s.emp_no = d.emp_no 7 WHERE 8 s.TO_DATE = '9999-01-01'--篩選條件 9 AND d.TO_DATE = '9999-01-01'
查找所有已經分配部門的員工的last_name和first_name
解題步驟:
題目:查找所有已經分配部門的員工的last_name和first_name
目標:查詢員工的 last_name,first_name,題目隱藏要顯示dept_no
篩選條件:已分配部門的員工
答案:
1 SELECT 2 e.last_name, 3 e.first_name, 4 d.dept_no 5 FROM 6 employees e--通過左聯,確認員工已分配部門 7 LEFT JOIN dept_emp d ON d.emp_no = e.emp_no 8 WHERE 9 d.dept_no != ''--防止關聯為空
查找所有員工的last_name和first_name以及對應部門編號dept_no,也包括展示沒有分配具體部門的員工
解題步驟:
題目:查找所有員工的last_name和first_name以及對應部門編號dept_no,也包括展示沒有分配具體部門的員工
目標:查詢員工的 last_name,first_name,題目隱藏要顯示dept_no,沒有分配具體部門的員工
篩選條件:已分配部門的員工
答案:
1 SELECT 2 ep.last_name, 3 ep.first_name, 4 dp.dept_no 5 FROM 6 employees ep --人員信息表為主表,左聯,一位部門可能為空,所以關聯后就會包含未分配部分的人 7 LEFT JOIN dept_emp dp ON ep.emp_no = dp.emp_no
查找所有員工入職時候的薪水情況,給出emp_no以及salary, 並按照emp_no進行逆序
解題步驟:
題目:查找所有員工入職時候的薪水情況,給出emp_no以及salary, 並按照emp_no進行逆序
目標: 查詢薪水情況,顯示emp_no以及salary(select 要顯示的字段)
篩選條件:員工入職時間,並按照emp_no進行逆序
答案:
1 SELECT --顯示字段 2 e.emp_no, 3 s.salary 4 FROM 5 employees e 6 LEFT JOIN salaries s ON e.emp_no = s.emp_no --確定是同一個人 7 AND e.hire_date = s.from_date --確定是入職時間 8 ORDER BY 9 e.emp_no DESC --倒序
查找薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t
解題步驟:
題目:查找薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t
目標: 查找員工號,漲幅次數(select 要顯示的字段)
篩選條件:漲幅超過15次
答案:
1 SELECT 2 emp_no, 3 SUM(1) --統計次數; 4 FROM 5 salaries 6 GROUP BY 7 emp_no --對每一個員工進行分組,然后統計其漲幅次數 8 HAVING 9 COUNT(1) > 15 --進行次數過濾
如果想詳細了解 sum(1),可以看這個文章:https://blog.csdn.net/qq_39313596/article/details/80623495
找出所有員工當前(to_date='9999-01-01')具體的薪水salary情況,對於相同的薪水只顯示一次,並按照逆序顯示
解題步驟:
題目:找出所有員工當前(to_date='9999-01-01')具體的薪水salary情況,對於相同的薪水只顯示一次,並按照逆序顯示
目標: 查找薪水(select 要顯示的字段)
篩選條件:當前時間(to_date),相同的僅顯示一次,逆序顯示
答案:
SELECT DISTINCT --去重 salary FROM salaries WHERE TO_DATE = '9999-01-01' ORDER BY salary DESC --倒序
獲取所有部門當前manager的當前薪水情況,給出dept_no, emp_no以及salary,當前表示to_date='9999-01-01'
解題步驟:
題目:獲取所有部門當前manager的當前薪水情況,給出dept_no, emp_no以及salary,當前表示to_date='9999-01-01'
目標: 查找dept_no, emp_no以及salary(select 要顯示的字段)
篩選條件:當前表示to_date='9999-01-01'
答案:
1 SELECT 2 d.dept_no, 3 s.emp_no, 4 s.salary 5 FROM --注意左關聯條件 6 dept_manager d 7 LEFT JOIN salaries s ON d.emp_no = s.emp_no 8 AND d.TO_DATE = s.TO_DATE 9 WHERE 10 d.TO_DATE = '9999-01-01'
獲取所有非manager的員工emp_no
解題步驟:
題目:獲取所有非manager的員工emp_no
目標: 查找emp_no(select 要顯示的字段)
篩選條件:非manager的員工
答案:
1 SELECT 2 em.emp_no 3 FROM 4 employees em 5 WHERE 6 NOT EXISTS ( --此處用了一個exists表達式,是管理者的員工,然后將這些排除就時非管理員的員工,此處也可以用not in,但是效率會降低一些 7 SELECT 8 1 9 FROM 10 dept_manager dm 11 WHERE 12 em.emp_no = dm.emp_no 13 )
題外閑談:exists,in;語法上區別,效率上區別;沒有覺得效率高低,看實際場景
這倆篇文章說的不錯,再次就不再贅述,唯一要注意的是exists的返回值是真或者假:https://blog.csdn.net/baidu_37107022/article/details/77278381,https://www.cnblogs.com/xuyufengme/p/9175929.html
獲取所有員工當前的manager,如果當前的manager是自己的話結果不顯示,當前表示to_date='9999-01-01'。
解題步驟:
題目:獲取所有員工當前的manager,如果當前的manager是自己的話結果不顯示,當前表示to_date='9999-01-01'
目標: 查找員工,當前的manager(select 要顯示的字段)
篩選條件:當前表示to_date='9999-01-01',如果當前的manager是自己的話結果不顯示
答案:
1 SELECT 2 de.emp_no, 3 dm.emp_no AS manager_no 4 FROM 5 dept_emp de 6 LEFT JOIN dept_manager dm ON de.dept_no = dm.dept_no 7 WHERE 8 de.emp_no != dm.emp_no 9 AND de.TO_DATE = '9999-01-01' 10 AND dm.TO_DATE = '9999-01-01'
獲取所有部門中當前員工薪水最高的相關信息,給出dept_no, emp_no以及其對應的salary
解題步驟:
題目:獲取所有部門中當前員工薪水最高的相關信息,給出dept_no, emp_no以及其對應的salary
目標: 查找部門,員工,薪水(select 要顯示的字段)
篩選條件:當前表示to_date='9999-01-01',
答案:
1 SELECT 2 de.dept_no, 3 de.emp_no, 4 MAX(sa.salary) --注意函數使用時機,什么時候需要group by,什么時候不需要 5 FROM 6 dept_emp de 7 LEFT JOIN salaries sa ON de.emp_no = sa.emp_no 8 WHERE 9 de.TO_DATE = '9999-01-01' --題目中默認為當前時間 10 AND sa.TO_DATE = '9999-01-01' 11 GROUP BY 12 de.dept_no --每個部門中最高的薪水的人,所以需要按照部門分組
從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。
解題步驟:
題目:從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。
目標: 查找title以及對應的數目t(select 要顯示的字段)
篩選條件:按照title進行分組,每組個數大於等於2
1 SELECT 2 title, 3 COUNT(1) AS t 4 FROM 5 titles 6 GROUP BY 7 title --分組 8 HAVING --配合分組使用,作用和where差不多 9 COUNT(1) >= 2
從titles表獲取按照title進行分組,注意對於重復的emp_no進行忽略。
解題步驟:
題目:從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。
注意對於重復的title進行忽略。
目標: 查找title以及對應的數目t(select 要顯示的字段)
篩選條件:按照title進行分組,每組個數大於等於2,注意對於重復的title進行忽略。
1 SELECT 2 title, 3 COUNT(DISTINCT(emp_no)) AS t --本題關鍵是對於重復的title進行忽略。也就是計數的時候要去重,注意 函數和distinct的使用方法 4 FROM 5 titles 6 GROUP BY 7 title 8 HAVING 9 COUNT(1) >= 2
關於count(distinct)的延伸
sql-按條件統計非重復值,count(distinct case when)使用 背景 項目中,遇到一個統計需求,從某張表中按照條件分別統計。剛開始想到用union all的寫法,太臃腫,后來使用count(distinct case when)解決此問題 count 數據統計中,count出現最頻繁 最簡單的用法 select count(*) from table where .... select count(distinct xx) from table where ... 但最簡單的用法也有其深刻的地方,比如這里其實有3種寫法,count(1)、count(*)、count(字段),它們有什么區別呢? count(1) 和 count(*) count(1)和count(*)差別不大,使用count(*)時,sql會幫你自動優化,指定到最快的字段。所以推薦使用count(*) count(*) 和 count(字段) count(*)會統計所有行數,count(字段)不會統計null值 count(case when) 條件統計,即對某個table分條件統計,比如表test_db,有一個字段user_id(可能重復), gender(man、women),需要統計man和women的人數 可以使用where分別統計 select count(distinct user_id) as man_cnt from test_db where gender = 'man' select count(distinct user_id) as women_cnt from test_db where gender = 'women' 也可以使用按條件統計 select count(distinct case gender = 'man' then user_id end) as man_cnt --至於case when,本人沒用過,不過也很少有這個使用場景吧 , count(distinct case gender = 'women' then user_id end) as woman_cnt from test_db
查找employees表所有emp_no為奇數,且last_name不為Mary的員工信息,並按照hire_date逆序排列
解題步驟:
題目:查找employees表所有emp_no為奇數,且last_name不為Mary的員工信息,並按照hire_date逆序排列
目標: 查找所有員工信息(select 要顯示的字段)
篩選條件:ast_name不為Mary,emp_no為奇數
1 SELECT 2 * 3 FROM 4 employees 5 where emp_no%2 != 0 --如果emp_no為索引列,會導致索引失效 6 AND last_name != 'Mary' 7 order by hire_date desc
拓展:索引列上計算引起的索引失效及優化措施以及注意事項;索引失效的情況有哪些?索引何時會失效?(全面總結)
兩個示例 例子一 表結構 DROP TABLE IF EXISTS `account`; CREATE TABLE IF NOT EXISTS `account` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `account` int(10) unsigned NOT NULL, `password` char(32) NOT NULL, `ip` char(15) NOT NULL, `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `time` (`time`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 比如要統計2012年08月15日注冊的會員數: SELECT count(id) FROM account WHERE DATEDIFF("2012-08-15",time)=0 例子二 表結構 DROP TABLE IF EXISTS `active`; CREATE TABLE IF NOT EXISTS `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `userid` int(10) unsigned NOT NULL, `lastactive` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `lastactive` (`lastactive`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 統計最近3分鍾的活躍用戶 SELECT count(id) FROM user WHERE unix_timstamp()-lastactive < 180 以上兩個例子中,雖然都建有索引,但是SQL執行中卻不走索引,而采用全表掃描。 原因揭密 SQL語句where中如果有functionName(colname)或者某些運算,則MYSQL無法使用基於colName的索引。使用索引需要直接查詢某個字段。 索引失效的原因是索引是針對原值建的二叉樹,將列值計算后,原來的二叉樹就用不上了; 為了解決索引列上計算引起的索引失效問題,將計算放到索引列外的表達式上。 解決辦法 例子一:SELECT count(id) FROM account WHERE time between "2012-08-15 00:00:00" and "2012-08-15 23:59:59" 例子二:SELECT count(id) FROM user WHERE lastactive > unix_timstamp() - 180 相關內容 1、如果對時間字段進行查找,可以將時間設置為int unsigned類型,存取UNIX時間戳。因為整型比較速度快 2、當我們執行查詢的時候,MySQL只能使用一個索引。 3、MySQL只有對以下操作符才使用索引: < , <= , = , > , >= , BETWEEN , IN ,以及某些時候的LIKE。可以在LIKE操作中使用索引的情形是指另一個操作數不是以通配符( % 或者 _ )開頭的情形。例如, “SELECT peopleid FROM people WHERE firstname LIKE 'Mich%';” 這個查詢將使用索引,但 “SELECT peopleid FROM people WHERE firstname LIKE '%ike';” 這個查詢不會使用索引。 不得不說 創建索引、優化查詢以便達到更好的查詢優化效果。但實際上,MySQL有時並不按我們設計的那樣執行查詢。MySQL是根據統計信息來生成執行計划的,這就涉及索引及索引的刷選率,表數據量,還有一些額外的因素。 Each table index is queried, and the best index is used unless the optimizer believes that it is more efficient to use a table scan. At one time, a scan was used based on whether the best index spanned more than 30% of the table, but a fixed percentage no longer determines the choice between using an index or a scan. The optimizer now is more complex and bases its estimate on additional factors such as table size, number of rows, and I/O block size. 簡而言之,當MYSQL認為符合條件的記錄在30%以上,它就不會再使用索引,因為mysql認為走索引的代價比不用索引代價大,所以優化器選擇了自己認為代價最小的方式。事實也的確如此 實例檢測 表結構 DROP TABLE IF EXISTS `active`; CREATE TABLE IF NOT EXISTS `active` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `userid` int(10) unsigned NOT NULL, `lastactive` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `lastactive` (`lastactive`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 插入數據 insert into active values (null,10000, unix_timestamp("2012-08-20 15:10:02")), (null,10001, unix_timestamp("2012-08-20 15:10:02")), (null,10002, unix_timestamp("2012-08-20 15:10:03")), (null,10003, unix_timestamp("2012-08-20 15:10:03")), (null,10004, unix_timestamp("2012-08-20 15:10:03")), (null,10005, unix_timestamp("2012-08-20 15:10:04")), (null,10006, unix_timestamp("2012-08-20 15:10:04")), (null,10007, unix_timestamp("2012-08-20 15:10:05")), (null,10008, unix_timestamp("2012-08-20 15:10:06")) explain select * from active where lastactive > unix_timestamp()-3; 上面這句索引起作用。 但是我在測試中,因為插入的日期與我測試的當前日期相差不少時間。所以我改寫為以下內容: explain select * from active where lastactive > unix_timestamp("2012-08-20 15:10:06") - 3; 但是數據顯示,TYPE為ALL,key為NULL。也就是說索引不起作用。 我在改寫以下語句測試: explain select * from active where lastactive > unix_timestamp("2012-08-20 15:10:06"); 上面這個語句,索引又起作用了。 一個疑惑 正好手頭上有一個12016條記錄的數據,證實一下“當MYSQL認為符合條件的記錄在30%以上,它就不會再使用索引”的結論。經過測試,在總記錄12016條記錄的表中,查詢小於1854條記錄時走索引,大於該記錄時不走索引。符合條件的記錄在15.4%。這....,30%的數據可能有待確認,正如上面說的那樣,MySQL的優化器是考慮多方面因素,並選擇自己認為代價最小的方式。 mysql自己判斷是否使用索引,如果你自己確信使用索引可以提高效率,你也可以強行實用索引force index(index_name)
統計出當前各個title類型對應的員工當前(to_date='9999-01-01')薪水對應的平均工資。結果給出title以及平均工資avg。
解題步驟:
題目:統計出當前各個title類型對應的員工當前(to_date='9999-01-01')薪水對應的平均工資。結果給出title以及平均工資avg。
目標: 查找結果給出title以及平均工資avg。(select 要顯示的字段)
篩選條件:默認為當前時間
1 SELECT 2 t.title, 3 AVG(s.salary) AS avg 4 FROM 5 salaries s 6 LEFT JOIN titles t ON s.emp_no = t.emp_no 7 WHERE 8 s.TO_DATE = '9999-01-01' 9 AND t.TO_DATE = '9999-01-01' 10 GROUP BY 11 t.title
獲取當前(to_date='9999-01-01')薪水第二多的員工的emp_no以及其對應的薪水salary
題目:獲取當前(to_date='9999-01-01')薪水第二多的員工的emp_no以及其對應的薪水salary
目標: 查找emp_no以及其對應的薪水salary(select 要顯示的字段)
篩選條件:薪水第二多
1 SELECT 2 emp_no, 3 salary 4 FROM 5 salaries 6 WHERE 7 TO_DATE = '9999-01-01' 8 ORDER BY 9 salary DESC --本題精髓,第二多,可以理解成倒序排第二的人 10 limit 11 1,1 --從第二條開始,去一條;也就是取得第二條
查找員工編號emp_no為10001其自入職以來的薪水salary漲幅值growth
題目:查找員工編號emp_no為10001其自入職以來的薪水salary漲幅值growth
目標: 查找漲幅值growth(select 要顯示的字段)
篩選條件:自入職以來,號emp_no為10001
1 SELECT 2 MAX(salary) - MIN(salary) AS growth --函數的使用,計算,以及起別名 as的語法 3 FROM 4 salaries 5 WHERE 6 emp_no = '10001';
針對actor表創建視圖actor_name_view,只包含first_name以及last_name兩列,並對這兩列重新命名,first_name為first_name_v,last_name修改為last_name_v:
終於到了聽起來牛逼點的題目啦!!!,其實也沒啥~~~,還是查詢
題目:針對actor表創建視圖actor_name_view,只包含first_name以及last_name兩列,並對這兩列重新命名,first_name為first_name_v,last_name修改為last_name_v:
目標: 創建這個視圖
篩選條件:
1 CREATE VIEW actor_name_view AS 2 SELECT 3 first_name AS first_name_v, 4 last_name AS last_name_v 5 FROM 6 actor
針對salaries表emp_no字段創建索引idx_emp_no,查詢emp_no為10005, 使用強制索引。
題目:針對salaries表emp_no字段創建索引idx_emp_no,查詢emp_no為10005, 使用強制索引。
目標:使用強制索引
篩選條件:
1 SELECT 2 * 3 FROM 4 salaries indexed 5 by idx_emp_no --使用強制索引 6 WHERE 7 emp_no = 10005
拓展:使用強制索引的案例
在last_update后面新增加一列名字為create_date
題目:修改表結構,用sql(這樣比手寫顯得牛逼)
目標:alter用法
篩選條件:
1 ALTER TABLE actor ADD 'create_date' datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
構造一個觸發器audit_log,在向employees_test表中插入一條數據的時候,觸發插入相關的數據到audit中。
題目: 構造一個觸發器audit_log,在向employees_test表中插入一條數據的時候,觸發插入相關的數據到audit中。(聽着就很高級,雖然實際中從未用過)
目標:
篩選條件:
1 CREATE TRIGGER audit_log AFTER 2 INSERT ON employees_test 3 BEGIN 4 INSERT INTO audit VALUES ( 5 new.id, 6 new.name 7 ); 8 9 END;
使用含有關鍵字exists查找未分配具體部門的員工的所有信息。
題目: 使用含有關鍵字exists查找未分配具體部門的員工的所有信息。
目標:查找員工的所有信息。
篩選條件:未分配具體部門
1 SELECT 2 * 3 FROM 4 employees e 5 WHERE 6 NOT EXISTS ( --就是exists的使用,上面有詳細講解過的,注意返回值是邏輯真假 7 SELECT 8 1 9 FROM 10 dept_emp de 11 WHERE 12 e.emp_no = de.emp_no 13 )