1. Lighthouse

Level 5 · Monthly salary sheet

The request

From Laura Bennett, Head of Finance

“I'm moving our payroll budget into a monthly plan. Can you pull everyone's full name, department and yearly salary, next to what it works out to per month?”

Your goal

From employees, return employee_id, full_name (first_name, a space, then last_name, as one text value), department, salary and monthly_salary (salary divided by 12, rounded to 2 decimals). Include every employee.

  • Read from the employees tablenot done yet
  • Show exactly employee_id full_name department salary monthly_salarynot done yet
  • 60 rowsnot done yet

Your query

SQL

Loading the editor…

    ResultPreview of employees · press Run to see yours
    Preview of employees
    employee_idfirst_namelast_namedepartmenttitle
    1CatherineHaleExecutiveChief Executive Officer
    2RobertKimExecutiveChief Operating Officer
    3MeganCollinsSalesHead of Sales
    4ChloeGutierrezSalesAccount Executive

    Mote checks your result

    Press Run. Each row that matches the goal becomes a firefly in your lantern.

    Tables

    Harbor & Pine store data, ready to query.

    employees60 rows · 8 columns
    • employee_idinteger
    • first_namevarchar
    • last_namevarchar
    • departmentvarchar
    • titlevarchar
    • manager_idinteger
    • hire_datedate
    • salaryinteger
    First 5 rows of employees
    employee_idfirst_namelast_namedepartmenttitlemanager_idhire_datesalary
    1CatherineHaleExecutiveChief Executive OfficerNULL2016-03-01285000
    2RobertKimExecutiveChief Operating Officer12017-01-09235000
    3MeganCollinsSalesHead of Sales12018-04-16172000
    4ChloeGutierrezSalesAccount Executive32020-01-2172000
    5FrankBellSalesAccount Executive32023-05-2173000
    customers2,018 rows · 9 columns
    • customer_idinteger
    • first_namevarchar
    • last_namevarchar
    • emailvarchar
    • cityvarchar
    • statevarchar
    • signup_datedate
    • segmentvarchar
    • referral_sourcevarchar
    First 5 rows of customers
    customer_idfirst_namelast_nameemailcitystatesignup_datesegmentreferral_source
    1OwenHudsonowen.hudson@icloud.comSan FranciscoCA2022-06-02consumersearch
    2DouglasMendozadmendoza69@gmail.comAtlantaGA2022-06-02consumerNULL
    3HenryBrookshbrooks@lakesidecafe.comLos AngelesCA2022-06-04businessNULL
    4BrianGrahambgraham@bluecedarhomes.comSeattleWA2022-06-06businesspinterest
    5KyleJimenezkjimenez27@yahoo.comIndianapolisIN2022-06-07consumerNULL
    products120 rows · 8 columns
    • product_idinteger
    • namevarchar
    • categoryvarchar
    • subcategoryvarchar
    • unit_pricedecimal
    • unit_costdecimal
    • launched_ondate
    • is_activeboolean
    First 5 rows of products
    product_idnamecategorysubcategoryunit_priceunit_costlaunched_onis_active
    101Vale Velvet LoveseatFurnitureSofas1659.00NULL2023-09-11true
    102Alder Oak Coffee TableFurnitureTables919.00503.502024-05-16true
    103Orchard Rattan Dining ChairFurnitureChairs789.00429.872023-05-27true
    104Upland Oak BookcaseFurnitureStorage429.00214.702022-12-20true
    105Avery Leather Bed FrameFurnitureBeds449.00232.702021-08-31true
    orders12,000 rows · 7 columns
    • order_idinteger
    • customer_idinteger
    • order_datetimestamp
    • statusvarchar
    • channelvarchar
    • shipping_feedecimal
    • coupon_codevarchar
    First 5 rows of orders
    order_idcustomer_idorder_datestatuschannelshipping_feecoupon_code
    10011252023-01-01 20:51:19completedweb0.00NULL
    10021562023-01-02 07:58:46completedweb0.00NULL
    1003222023-01-02 10:25:27completedmarketplace4.99WELCOME10
    1004482023-01-02 11:21:51completedmarketplace4.99WELCOME10
    1005822023-01-02 11:43:36completedweb0.00WELCOME10
    order_items30,338 rows · 6 columns
    • order_item_idinteger
    • order_idinteger
    • product_idinteger
    • quantityinteger
    • unit_pricedecimal
    • discount_pctdecimal
    First 5 rows of order_items
    order_item_idorder_idproduct_idquantityunit_pricediscount_pct
    11001121931.990.00
    21001154311.990.00
    31002154411.990.00
    410021941149.000.00
    51002193219.990.00
    returns1,673 rows · 5 columns
    • return_idinteger
    • order_item_idinteger
    • returned_ondate
    • reasonvarchar
    • refund_amountdecimal
    First 5 rows of returns
    return_idorder_item_idreturned_onreasonrefund_amount
    1142023-01-10damaged83.69
    2422023-01-10wrong_item19.99
    31052023-01-14wrong_item10.99
    4242023-01-16changed_mind26.99
    51262023-01-16late20.99
    web_sessions40,000 rows · 7 columns
    • session_idinteger
    • customer_idinteger
    • started_attimestamp
    • devicevarchar
    • sourcevarchar
    • pages_viewedinteger
    • convertedboolean
    First 5 rows of web_sessions
    session_idcustomer_idstarted_atdevicesourcepages_viewedconverted
    1NULL2023-01-01 23:02:24mobilepaid1false
    2182023-01-01 15:07:49desktoppaid1false
    3NULL2023-01-01 16:55:46desktopdirect7false
    4NULL2023-01-01 12:43:28mobileorganic3false
    5NULL2023-01-01 13:06:21mobilesocial2false
    marketing_spend3,276 rows · 3 columns
    • spend_datedate
    • channelvarchar
    • amountdecimal
    First 5 rows of marketing_spend
    spend_datechannelamount
    2023-01-01paid492.99
    2023-01-01email37.38
    2023-01-01social200.53
    2023-01-02paid709.13
    2023-01-02email64.13

    The lesson

    This ticket uses the moves from the margin level, on a new table: employees, one row per person at Harbor & Pine, with a yearly salary in whole dollars. Two columns are built rather than picked: one from text, one from numbers.

    Gluing text and doing math in the SELECT list

    || is the SQL operator that joins text values end to end. Put a literal space between the names, or they run together. Arithmetic works the same way, one row at a time:

    SELECT
      first_name || ' ' || last_name AS full_name,
      salary,
      ROUND(salary / 12.0, 2) AS monthly_salary
    FROM employees;

    The first two rows are Catherine Hale, 285,000 a year and 23,750 a month, and Robert Kim, 235,000 a year and 19,583.33 a month. CONCAT(first_name, ' ', last_name) gives the same text and is available in almost every database.

    salary / 12.0 uses 12.0 on purpose. DuckDB, the engine in this game, returns a decimal for salary / 12 anyway, but several databases throw the remainder away when both sides are integers. Writing 12.0 makes the division decimal everywhere, so the query survives being pasted into the company warehouse.

    Common mistakes

    • Concatenating a column that can be NULL. With ||, one NULL makes the whole string NULL. No employee name is missing here, but the next levels deal with it.
    • Rounding too early. Round once, in the final column. A rounded monthly figure multiplied back by 12 drifts away from the real salary.
    • Writing first_name + ' ' + last_name. In DuckDB and Postgres + is for numbers only, so the database tries to add text and reports an error. Use || or CONCAT for text.
    • Calling the new column name. It works, but full_name says what is in it, and the products table already has a name column that means something else.
    • Dropping the original column. Keep salary next to monthly_salary, so the reader can check the math on any row by eye. Laura asked for both on purpose.

    In SQL Server

    SQL Server joins text with + (or CONCAT), and salary / 12 on an INT column truncates to a whole number there:

    SELECT FirstName + ' ' + LastName AS FullName,
           ROUND(Salary / 12.0, 2) AS MonthlySalary
    FROM Employees;

    Pick what may run on this site. You can change this any time from "Cookie settings" at the bottom of every page.