{
  "assessmentTests": {
    "sql_test": {
      "name": "SQL 測驗",
      "desc": "30 道關於篩選、聯接、NULL 語義、聚合、子查詢和視窗函式的情景題 — 判斷你對 SQL 的理解是否與職位要求的 SQL 工作能力相符。",
      "recommendation": "你的 SQL 技能概覽",
      "results": {
        "beginner": {
          "name": "初級",
          "desc": "你能寫出一個有效的 SELECT 語句並在幾個條件上進行篩選，但你錯的題往往聚焦在 NULL 處理和聯接機制上，而不是語法——把一列與 NULL 用 = 比較、LEFT JOIN 實際保留什麼、BETWEEN 的邊界如何工作。這都不是說你資料庫能力不行；這些是學 SQL 時透過試錯而不是透過標準學來的人容易踩雷的特定規則。在工作中很重要，因為每一個這樣的坑都是查詢返回看似合理但其實錯誤的行數的地方。",
          "recommendation": "先集中學三樣東西，按這個順序：為什麼 WHERE col = NULL 永遠匹配不了任何東西（必須用 IS NULL），INNER JOIN 如何丟棄不匹配的行而 LEFT JOIN 保留它們，以及 BETWEEN 的確切邊界。Mode Analytics 的 SQL 教程和 PostgreSQL 文件都用可執行的例子講了這三個。"
        },
        "intermediate": {
          "name": "中級",
          "desc": "你日常報表查詢寫得很順手 — 聯接、GROUP BY、直白的篩選 — 日常儀表板或臨時分析工作不會讓你放慢速度。從這裡到高級的差距主要在子句互相作用會發生什麼：一個寫在聯接右表上的 WHERE 子句偷偷把 LEFT JOIN 轉回 INNER JOIN、一個聯接在應用聚合前扇出行數、一個 NOT IN 因為一個 NULL 偷偷滑進子查詢就無聲地返回什麼都不是。這些是透過眼神檢查就能過關但只有在某人跟另一份報表對比總數時才會顯露的 bug。",
          "recommendation": "專注子句如何互相作用而不是每個子句單獨做什麼：WHERE 在 LEFT JOIN 右表上篩選、一對多聯接在聚合前扇出行數、為什麼 NOT IN 在 NULL 存在時會壞掉（EXISTS 通常不會）。然後學 HAVING vs WHERE，因為那個拆分容易絆倒已經分別知道兩個子句的人。"
        },
        "advanced": {
          "name": "高級",
          "desc": "這是大多數職位招募資訊說的「懂 SQL」的等級。你讀一個多聯接查詢能在執行它前預測它的行數，你知道為什麼一個結果集改變了而不只是知道它改變了，你遇到清晰工具的地方會選擇 CTE 或視窗函式而不是巢狀子查詢。把這個等級和頂級分開的是防守工作的一側：知道什麼時候有並列值關鍵的排名函式是哪個、什麼時候一個事務隔離出併發會話的內容、一個缺失的 ON DELETE 規則在資料庫級別真正做什麼。",
          "recommendation": "深入那些保護別人也要動的資料的部分：RANK、DENSE_RANK 和 ROW_NUMBER 在有並列值時的區別、COMMIT 實際讓誰看到什麼、外部索引鍵在 DELETE 上的行為。用 The Index 通訊或 SQL for Devs 在視窗函式和事務隔離上的深度潛水作為這兩個的下一步。"
        },
        "expert": {
          "name": "專家",
          "desc": "你在每一部分都拿了高分 — 篩選和 NULL 語義、聯接和集合運算、聚合和子查詢、視窗函式、CTE 和約束。實際上這意味著你可以被扔進一個陌生人的多聯接報表查詢，解釋為什麼它返回它返回的行數，而不只是語法說它應該返回什麼，後者才是更難、更有價值的技能。在這個等級，查詢語言很少是限制因子；限制通常來自模式設計或它下面資料的大小。",
          "recommendation": "收益現在來自執行計劃和設計：在假設一個查詢慢前讀 EXPLAIN 輸出、索引策略作為對寫成本的權衡而不是免費勝利、和隨著模式增長而堅持的歸一化決定。如果你在因一個職位而被篩選，講一個你在生產中找到的查詢 bug，比如聯接扇出或 NOT IN/NULL 陷阱，而不是列舉 SQL 特性 — 這展示的是你的推理能力，不只是詞彙。"
        }
      },
      "questions": [
        {
          "question": "一個表有一個可空的 age 列。你執行 SELECT * FROM users WHERE age = NULL。這會返回多少行，即使有幾行的 age 被設成 NULL？",
          "options": [
            {
              "icon": "",
              "label": "age 為 NULL 的每一行"
            },
            {
              "icon": "",
              "label": "0 行"
            },
            {
              "icon": "",
              "label": "返回錯誤"
            },
            {
              "icon": "",
              "label": "所有行"
            }
          ]
        },
        {
          "question": "你執行 SELECT DISTINCT department, role FROM employees。DISTINCT 移除什麼的重複？",
          "options": [
            {
              "icon": "",
              "label": "department 和 role 的每種組合"
            },
            {
              "icon": "",
              "label": "僅 department 的重複值"
            },
            {
              "icon": "",
              "label": "僅 role 的重複值"
            },
            {
              "icon": "",
              "label": "不移除任何重複，DISTINCT 只作用於單個列"
            }
          ]
        },
        {
          "question": "一個 name 列用 WHERE name LIKE 'A_' 篩選。這些值中哪個匹配：'A'、'Al'、'Ana'、'Ally'？",
          "options": [
            {
              "icon": "",
              "label": "'A'"
            },
            {
              "icon": "",
              "label": "'Al'"
            },
            {
              "icon": "",
              "label": "'Ana' 和 'Ally'"
            },
            {
              "icon": "",
              "label": "全部四個值"
            }
          ]
        },
        {
          "question": "一個 price 列用 WHERE price BETWEEN 10 AND 20 篩選。price 恰好 10 或恰好 20 的行會被包含嗎？",
          "options": [
            {
              "icon": "",
              "label": "不會，兩者都被排除"
            },
            {
              "icon": "",
              "label": "會，兩者都包含在內"
            },
            {
              "icon": "",
              "label": "只有 price = 10"
            },
            {
              "icon": "",
              "label": "只有 price = 20"
            }
          ]
        },
        {
          "question": "一個表 orders 有 10 行，其中 3 行的 shipped_date 是 NULL。SELECT COUNT(*) FROM orders 返回什麼，SELECT COUNT(shipped_date) FROM orders 返回什麼？",
          "options": [
            {
              "icon": "",
              "label": "10 然後 10"
            },
            {
              "icon": "",
              "label": "7 然後 7"
            },
            {
              "icon": "",
              "label": "10 然後 7"
            },
            {
              "icon": "",
              "label": "10 然後 3"
            }
          ]
        },
        {
          "question": "你執行 SELECT name, salary FROM employees ORDER BY 2 DESC。2 指的是什麼？",
          "options": [
            {
              "icon": "",
              "label": "會產生語法錯誤"
            },
            {
              "icon": "",
              "label": "結果的第二行"
            },
            {
              "icon": "",
              "label": "文字值 2，用作並列符"
            },
            {
              "icon": "",
              "label": "SELECT 列表中的第二列 salary"
            }
          ]
        },
        {
          "question": "在標準 SQL 中，'Ana' || ' ' || 'Lee' 計算為什麼？",
          "options": [
            {
              "icon": "",
              "label": "這會導致語法錯誤"
            },
            {
              "icon": "",
              "label": "TRUE"
            },
            {
              "icon": "",
              "label": "'AnaLee'"
            },
            {
              "icon": "",
              "label": "'Ana Lee'"
            }
          ]
        },
        {
          "question": "哪個完全等價於 WHERE status IN ('open', 'pending', 'review')？",
          "options": [
            {
              "icon": "",
              "label": "WHERE status = 'open' AND status = 'pending' AND status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status != 'open' OR status != 'pending' OR status != 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status = 'open' OR status = 'pending' OR status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status LIKE 'open,pending,review'"
            }
          ]
        },
        {
          "question": "customers 有 100 行；其中 20 行從未下過訂單。你執行 SELECT c.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id。這 20 個沒有訂單的客戶會出現在結果中嗎？",
          "options": [
            {
              "icon": "",
              "label": "會，每個一次，o.id 顯示為 NULL"
            },
            {
              "icon": "",
              "label": "會，但只有他們也出現在 WHERE 子句中時"
            },
            {
              "icon": "",
              "label": "不會"
            },
            {
              "icon": "",
              "label": "會，在 orders 中的每列複製一次"
            }
          ]
        },
        {
          "question": "你想要每個客戶不管他們是否有訂單，所以你寫 SELECT c.id, o.total FROM customers c LEFT JOIN orders o ON c.id = o.customer_id WHERE o.total > 100。這仍然會返回零訂單的客戶嗎？",
          "options": [
            {
              "icon": "",
              "label": "不會，效果等同於 INNER JOIN"
            },
            {
              "icon": "",
              "label": "會，LEFT JOIN 會保留每一個客戶"
            },
            {
              "icon": "",
              "label": "會，且 o.total 顯示為 0"
            },
            {
              "icon": "",
              "label": "不會，效果等同於 RIGHT JOIN"
            }
          ]
        },
        {
          "question": "一個 employees 表有一個 id 列和一個指向另一行 id 的 manager_id 列。要列出每個員工旁邊他們的經理名字，你把表聯接到自身：SELECT e.name, m.name FROM employees e JOIN employees m ON e.manager_id = m.id。這個模式叫什麼？",
          "options": [
            {
              "icon": "",
              "label": "交叉聯接"
            },
            {
              "icon": "",
              "label": "遞迴聯接"
            },
            {
              "icon": "",
              "label": "自聯接"
            },
            {
              "icon": "",
              "label": "無效查詢"
            }
          ]
        },
        {
          "question": "兩個有相同列的 SELECT 查詢用 UNION 組合。如果兩個查詢都返回相同的行，那行在最終結果中會出現多少次？",
          "options": [
            {
              "icon": "",
              "label": "一次"
            },
            {
              "icon": "",
              "label": "兩次"
            },
            {
              "icon": "",
              "label": "零次"
            },
            {
              "icon": "",
              "label": "取決於哪個查詢先列出它"
            }
          ]
        },
        {
          "question": "表 sizes 有 3 行，colors 有 4 行。SELECT * FROM sizes CROSS JOIN colors 返回多少行？",
          "options": [
            {
              "icon": "",
              "label": "7"
            },
            {
              "icon": "",
              "label": "12"
            },
            {
              "icon": "",
              "label": "3"
            },
            {
              "icon": "",
              "label": "0"
            }
          ]
        },
        {
          "question": "orders 對訂單 #100 有 1 行，order_items 對訂單 #100 有 3 行（每行商品一行）。你執行 SELECT o.id, o.total FROM orders o JOIN order_items i ON o.id = i.order_id WHERE o.id = 100。有多少行來自訂單 #100？",
          "options": [
            {
              "icon": "",
              "label": "3"
            },
            {
              "icon": "",
              "label": "1"
            },
            {
              "icon": "",
              "label": "4"
            },
            {
              "icon": "",
              "label": "0"
            }
          ]
        },
        {
          "question": "SELECT c.name, o.id FROM customers c RIGHT JOIN orders o ON c.id = o.customer_id 返回和下面哪個一樣的行？",
          "options": [
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o LEFT JOIN customers c ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o CROSS JOIN customers c"
            }
          ]
        },
        {
          "question": "在標準 SQL 中，你執行 SELECT department, name, AVG(salary) FROM employees GROUP BY department。這是有效的查詢嗎？",
          "options": [
            {
              "icon": "",
              "label": "有效，按 department 分組就足夠了"
            },
            {
              "icon": "",
              "label": "無效，name 必須聚合或放入 GROUP BY"
            },
            {
              "icon": "",
              "label": "有效，SQL 會為每個部門選一個 name"
            },
            {
              "icon": "",
              "label": "無效，AVG() 不能與 GROUP BY 一起使用"
            }
          ]
        },
        {
          "question": "你想要平均薪資超過 80000 的部門。哪個子句在分組後篩選一個像 AVG(salary) 這樣的聚合值 — WHERE 還是 HAVING？",
          "options": [
            {
              "icon": "",
              "label": "WHERE"
            },
            {
              "icon": "",
              "label": "兩者都可以"
            },
            {
              "icon": "",
              "label": "都不行，需要用子查詢"
            },
            {
              "icon": "",
              "label": "HAVING"
            }
          ]
        },
        {
          "question": "你寫 SELECT salary * 1.1 AS new_salary FROM employees WHERE new_salary > 50000。這會執行嗎？",
          "options": [
            {
              "icon": "",
              "label": "是的，WHERE 可以使用 SELECT 別名"
            },
            {
              "icon": "",
              "label": "是的，但只對數字別名"
            },
            {
              "icon": "",
              "label": "不，帶篩選條件的查詢裡不允許用 AS"
            },
            {
              "icon": "",
              "label": "不，WHERE 在別名存在之前就已執行"
            }
          ]
        },
        {
          "question": "SELECT name FROM employees e WHERE salary > (SELECT AVG(salary) FROM employees WHERE department = e.department)。為什麼這叫一個關聯子查詢？",
          "options": [
            {
              "icon": "",
              "label": "它用 JOIN 代替了 WHERE 子句"
            },
            {
              "icon": "",
              "label": "它用外層查詢的 e.department"
            },
            {
              "icon": "",
              "label": "它返回的結果不止一列"
            },
            {
              "icon": "",
              "label": "它在外層查詢開始前只執行一次"
            }
          ]
        },
        {
          "question": "一個子查詢 SELECT manager_id FROM employees 返回一些 NULL 值和實際 ids。你執行 SELECT name FROM employees WHERE id NOT IN (SELECT manager_id FROM employees)。會發生什麼？",
          "options": [
            {
              "icon": "",
              "label": "返回所有非經理員工，忽略 NULL"
            },
            {
              "icon": "",
              "label": "返回 0 行"
            },
            {
              "icon": "",
              "label": "引發錯誤"
            },
            {
              "icon": "",
              "label": "返回所有員工"
            }
          ]
        },
        {
          "question": "SELECT name FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id)。這返回什麼？",
          "options": [
            {
              "icon": "",
              "label": "至少有一個訂單的所有客戶"
            },
            {
              "icon": "",
              "label": "所有客戶"
            },
            {
              "icon": "",
              "label": "返回錯誤"
            },
            {
              "icon": "",
              "label": "只有恰好有一個訂單的客戶"
            }
          ]
        },
        {
          "question": "你寫 SELECT name, (SELECT order_id FROM orders WHERE customer_id = c.id) AS last_order FROM customers c，並且一個給定的客戶有 3 行在 orders 中。當這個查詢執行時會發生什麼？",
          "options": [
            {
              "icon": "",
              "label": "只返回第一個"
            },
            {
              "icon": "",
              "label": "返回由逗號分隔的三個值"
            },
            {
              "icon": "",
              "label": "返回 3 行"
            },
            {
              "icon": "",
              "label": "執行時引發錯誤"
            }
          ]
        },
        {
          "question": "四行並列最高分。使用 RANK() ORDER BY score DESC，全部四行得到 rank 1。下一行得到什麼 rank？",
          "options": [
            {
              "icon": "",
              "label": "5"
            },
            {
              "icon": "",
              "label": "2"
            },
            {
              "icon": "",
              "label": "1"
            },
            {
              "icon": "",
              "label": "4"
            }
          ]
        },
        {
          "question": "四行並列最高分。使用 DENSE_RANK() ORDER BY score DESC，全部四行得到 rank 1。下一行得到什麼 rank？",
          "options": [
            {
              "icon": "",
              "label": "5"
            },
            {
              "icon": "",
              "label": "1"
            },
            {
              "icon": "",
              "label": "2"
            },
            {
              "icon": "",
              "label": "3"
            }
          ]
        },
        {
          "question": "SUM(amount) OVER (PARTITION BY region ORDER BY amount) 被加到一個查詢。PARTITION BY region 在這裡做什麼？",
          "options": [
            {
              "icon": "",
              "label": "它在每個 region 內重新累計求和"
            },
            {
              "icon": "",
              "label": "它篩選結果到單個 region"
            },
            {
              "icon": "",
              "label": "它把行合併成每個 region 一行"
            },
            {
              "icon": "",
              "label": "它按字母順序對 region 排序"
            }
          ]
        },
        {
          "question": "ROW_NUMBER() OVER (ORDER BY score DESC) 被應用到五行，其中兩行在分數上完全並列。兩行會得到相同的行號嗎？",
          "options": [
            {
              "icon": "",
              "label": "會"
            },
            {
              "icon": "",
              "label": "只有 PARTITION BY 也被用時"
            },
            {
              "icon": "",
              "label": "取決於並列出現的位置"
            },
            {
              "icon": "",
              "label": "不會"
            }
          ]
        },
        {
          "question": "WITH high_earners AS (SELECT * FROM employees WHERE salary > 100000) SELECT department, COUNT(*) FROM high_earners GROUP BY department。high_earners 是什麼？",
          "options": [
            {
              "icon": "",
              "label": "公用表表達式（CTE）"
            },
            {
              "icon": "",
              "label": "資料庫裡的一張永久表"
            },
            {
              "icon": "",
              "label": "在查詢結束後仍然保留的檢視"
            },
            {
              "icon": "",
              "label": "儲存過程"
            }
          ]
        },
        {
          "question": "一個列被宣告為 PRIMARY KEY。你能插入一行其中那列是 NULL 嗎？",
          "options": [
            {
              "icon": "",
              "label": "可以"
            },
            {
              "icon": "",
              "label": "可以，但只能有一行為 NULL"
            },
            {
              "icon": "",
              "label": "不可以"
            },
            {
              "icon": "",
              "label": "取決於該列的預設值"
            }
          ]
        },
        {
          "question": "在一個開啟的事務內，你執行一個 UPDATE 但還沒執行 COMMIT。從第二個分開的資料庫連線，那個更新可見嗎？",
          "options": [
            {
              "icon": "",
              "label": "是的，立即可見"
            },
            {
              "icon": "",
              "label": "僅當第二個連線開啟了事務時"
            },
            {
              "icon": "",
              "label": "取決於更新的是哪張表"
            },
            {
              "icon": "",
              "label": "不，在提交之前都不可見"
            }
          ]
        },
        {
          "question": "products.category_id 有一個引用 categories.id 的 FOREIGN KEY 約束。你試圖刪除一行從 categories，它仍有 products 指向它，沒有指定 ON DELETE 規則。會發生什麼？",
          "options": [
            {
              "icon": "",
              "label": "products 的 category_id 被設為 NULL"
            },
            {
              "icon": "",
              "label": "引用它的 products 也被刪除"
            },
            {
              "icon": "",
              "label": "DELETE 操作被拒絕"
            },
            {
              "icon": "",
              "label": "DELETE 成功，留下懸空引用"
            }
          ]
        }
      ],
      "optionOrderVersion": "f9e1314f9ea2bea2"
    }
  },
  "testNames": {
    "sql-test": "SQL 技能"
  }
}
