SQL面試通關祕籍:面試知識點+技巧分享!


SQL是用於數據分析和數據處理的最重要的編程語言之一,所以與數據科學相關的工做(例如數據分析師、數據科學家和數據工程師)在面試時總會問到關於 SQL 的問題。面試

SQL面試問題旨在評估應聘者的技術和解決問題的能力。所以對於應聘者來講,關鍵在於不只要根據樣本數據編寫出正確的查詢,並且還要像對待現實數據集同樣考慮各類場景和邊緣狀況數據庫

在這篇文章中,我將介紹 SQL 面試問題中常見的模式,並提供一些在 SQL 查詢中巧妙處理它們的技巧。編程

1dom

問問題編程語言

要搞定一場 SQL 面試,最重要的是儘可能多問問題,獲取關於給定任務和數據樣本的全部細節。充分理解需求後,接下來你就能夠節省不少迭代問題的時間,而且能很好地處理邊緣狀況。函數

我注意到許多候選人常常還沒徹底理解SQL問題或數據集,就直接開始編寫解決方案了。以後,等我指出他們解決方案中存在的問題後,他們只好反覆修改查詢。最後,他們在迭代中浪費了不少面試時間,甚至可能到最後都沒有找到正確的解決方案。ui

我建議你們在參加SQL面試時,就當成是本身在和業務夥伴共事。因此在你提供解決方案以前,應該要針對數據請求瞭解清楚全部的需求。spa

舉例:

查找薪水最高的前 3 名員工。code

樣本employee_salary表blog

這裏你應該要求面試官說清楚「前三名」具體是什麼意思。我應該在結果中包括 3 名員工嗎?你要我怎樣處理關係?此外,請仔細檢查樣本員工數據。salary 字段的數據類型是什麼?在計算以前是否須要清除數據?

2

選哪個JOIN

在SQL中,JOIN 一般用來合併來自多個表的信息。

有四種不一樣類型的 JOIN,但在大多數狀況下,咱們只使用INNER、LEFT和FULLJOIN,由於 RIGHTJOIN並非很直觀,還可使用 LEFTJOIN 很簡單地重寫。在 SQL 面試中,須要根據給定問題的特定要求選擇你要使用的正確JOIN。

舉例:

查找每一個學生參加的課程總數。(提供學生 id、姓名和選課的數量。)

樣本student和class_history表

你可能已經注意到了,並不是全部出如今 class_history 表中的學生都出如今了 student 表中,這多是由於這些學生已經畢業了。(這在事務數據庫中其實是很是典型的狀況,由於再也不活躍的記錄每每會被刪除。)

根據面試官是否但願結果中包含畢業生,咱們須要使用LEFT JOIN或 INNER JOIN來組合兩個表:

WITH class_count AS (
    SELECT student_id, COUNT(*) AS num_of_class
    FROM class_history
    GROUP BY student_id
)
SELECT 
    c.student_id,
    s.student_name,
    c.num_of_class
FROM class_count c
-- CASE 1: include only active students
JOIN student s ON c.student_id = s.student_id
-- CASE 2: include all students
-- LEFT JOIN student s ON c.student_id = s.student_id

3

GROUP BY

GROUP BY是SQL中最重要的功能,由於它普遍用於數據聚合。若是在一個 SQL 問題中看到諸如求和、平均值、最小值或最大值之類的關鍵字,這就代表你可能應該在查詢中使用GROUP BY了。

一個常見的陷阱是在GROUP BY過濾數據時混淆 WHERE和HAVING——我見過不少人犯了這個錯誤。

舉例:

計算每一個學生在每一個學年的必修課程平均 GPA,並找到每一個學期中符合 Dean’s List(GPA≥3.5)資格的學生。

樣本gpa_history表

因爲咱們在GPA計算中僅考慮必修課程,所以須要使用WHERE is_required=TRUE來排除選修課程。

咱們須要每位學生在每學年的平均GPA,所以咱們將同時GROUP BY student_id和school_year 列,並取gpa列的平均值。最後,咱們只保留學平生均 GPA高於3.5的行,可使用HAVING來實現。合起來是下面這樣:

SELECT 
    student_id,
    school_year,
    AVG(gpa) AS avg_gpa
FROM gpa_history
WHERE is_required = TRUE 
GROUP BY student_id, school_year
HAVING AVG(gpa) >= 3.5
注意:每當在查詢中使用GROUP BY時,都只能選擇group-by列和聚合列,由於其餘列中的行級信息已被捨棄。

4

SQL 查詢執行順序

大多數人會從SELECT開始,從上到下編寫SQL查詢。

但你知道SQL引擎執行函數時要到後面才執行SELECT嗎?如下是 SQL 查詢的執行順序:

  • FROM, JOIN
  • WHERE
  • GROUP BY
  • HAVING
  • SELECT
  • DISTINCT
  • ORDER BY
  • LIMIT, OFFSET

再次考慮前面的示例:

由於咱們想在計算平均GPA以前過濾掉選修課程,因此我使用WHERE is_required=TRUE代替HAVING,由於WHERE會在GROUP BY和HAVING以前執行。我不能編寫HAVING avg_gpa >= 3.5的緣由是,avg_gpa被定義爲SELECT的一部分,所以沒法在SELECT以前執行的步驟中引用它。

我建議在編寫查詢時遵循引擎的執行順序,這在編寫複雜查詢時會頗有用。

5

Window 函數

Window函數也常常出如今SQL面試中。共有五種常見的Window函數:

  • RANK/DENSE_RANK/ROW_NUMBER:它們經過排序特定列來爲每行分配一個排名。若是給出了任何分區列,則行將在其所屬的分區組中排名。
  • LAG/LEAD:它根據指定的順序和分區組從前一行或後一行檢索列值。

在SQL面試中,重要的是要瞭解排名函數之間的差別,並知道什麼時候使用LAG/LEAD

舉例:

查找每一個部門中薪水最高的前 3 名員工。

另外一個示例employee_salary表

當一個SQL問題要求計算「TOP N」時,咱們可使用ORDER BY或排名函數來回答問題。

但在這個示例中,它要求計算「每一個 Y 中的 TOP N X」,這強烈暗示咱們應該使用排名函數,由於咱們須要對每一個分區組中的行進行排名。

如下查詢剛好能找到 3 名薪水最高的員工,而不論他們的關係如何,以下:

WITH T AS (
SELECT 
    *,
    ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY employee_salary DESC) AS rank_in_dep
FROM employee_salary)
SELECT * FROM T
WHERE rank_in_dep <= 3 
-- Note: When using ROW_NUMBER, each row will have a unique rank number and ranks for tied records are assigned randomly. For exmaple, Rimsha and Tiah may be rank 2 or 3 in different query runs.

此外,根據關係的處理方式,咱們能夠選擇其餘排名函數。一樣,細節是很重要的!

ROW_NUMBER,RANK,DENSE_RANK結果比較

6

重複項

SQL面試中的另外一個常見陷阱是忽略數據重複

儘管樣本數據中的某些列彷佛具備不一樣的值,但面試官仍是但願候選人考慮全部可能性,就像他們在處理真實數據集同樣。

例如:

在上一個示例employee_salary表中,可讓僱員共享相同的名稱。

要避免由重複項致使的潛在問題,一種簡單方法是始終使用 ID 列惟一地標識不一樣的記錄。

舉例:

使用 employee_salary 表查找每一個部門全部員工的總薪水。

正確的解決方案是 GROUP BY employee_id,而後使用 SUM(employee_salary) 計算總薪水。若是須要僱員姓名,請在末尾與 employee 表聯接以檢索僱員姓名信息。

錯誤的方法是使用 GROUP BY employee_name。

7

NULL

在SQL中,任何謂詞均可以產生三個值之一true,false和NULL,後者是unknown或missing數據值的保留關鍵字。處理NULL數據集時可能會意外地很棘手。

在SQL面試中,面試官可能會特別注意解決方案是否處理了NULL值。有時,很明顯有一列是不能nullabl的,但對於其餘大多數列來講,頗有可能會有NULL值。

建議:確認示例數據中的關鍵列是否爲nullable,

若是能夠,請利用IS(NOT)NULL,IFNULL和COALESCE 之類的函數來覆蓋這些邊緣狀況。

8

交流

最後一點也很是重要:在SQL面試期間要隨時與面試官溝通交流。

我面試過的許多候選人都很沉默寡言,有疑問的時候纔會知聲。固然若是他們最終給出了完美的解決方案,那也不是什麼問題。

可是,在技術面試期間保持溝通交流每每會是有價值的。

例如:你能夠談論對問題和數據的理解,說明你計劃如何解決問題,爲何使用某些函數而不是其餘選項,以及正在考慮哪些極端狀況。

9

總結

  • 首先要提問,收集所需的細節
  • 在INNER,LEFT和FULL JOIN之間謹慎選擇
  • 使用GROUP BY聚合數據並正確使用WHERE和HAVING
  • 瞭解三個排名函數之間的差別
  • 知道什麼時候使用LAG/LEAD窗口函數
  • 若是在建立複雜的查詢時遇到困難,請嘗試遵循SQL執行順序
  • 考慮潛在的數據問題,例如重複和NULL值
  • 與面試官交流你的思路
Xinran Waibel | 做者
王強 | 譯者
https://www.infoq.cn/article/...

相關文章
相關標籤/搜索