runtime
72 / 88

lesson 72 Warehouse & reporting projects · advanced

Silver: clean, map & deduplicate

Clean values, apply mappings and remove duplicate records.

the idea

Silver applies explicit quality rules. Normalize keys and text, keep the latest customer version, map country codes, and exclude missing keys. With equal version timestamps production logic needs an additional reliable tie-breaker; this sample has none.

tables in this lesson

The challenges use this data. Each column shows its type underneath; → marks a link to another table.

bronze_customers4 columns · 7 rows
raw_idtextnametextcountrytextupdated_attext
C001 Alice USA2025-01-01
C001 Alice Nguyen US2025-01-05
C002BenGB2025-01-02
C003 Cara UK2025-01-03
C004DevIND2025-01-04

showing 5 of 7 rows

example

The idea in one query. Press Run to see what it returns; running examples never affects your progress.

example.sql
CREATE TEMP TABLE silver_customers AS
WITH ranked AS(
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY TRIM(raw_id) ORDER BY updated_at DESC) AS rn
  FROM bronze_customers
  WHERE raw_id IS NOT NULL AND TRIM(raw_id)<>''
)
SELECT
  TRIM(raw_id) AS customer_id,
  TRIM(name) AS name,
  CASE UPPER(TRIM(country))
    WHEN 'US' THEN 'United States'
    WHEN 'USA' THEN 'United States'
    WHEN 'UK' THEN 'United Kingdom'
    WHEN 'GB' THEN 'United Kingdom'
    WHEN 'IND' THEN 'India'
    WHEN 'CA' THEN 'Canada'
    ELSE UPPER(TRIM(country))
  END AS country
FROM ranked
WHERE rn=1;
SELECT customer_id,name,country
FROM silver_customers;

Watch for: Keep the source unchanged and make exclusion rules visible. A new surrogate key is not a substitute for deduplication.

build it step by step

Each step changes one thing. Run them in order and watch the result change.

  1. Profile duplicate natural keys. Bronze keeps every source version. Silver will trim keys, map countries, and keep the latest updated_at per key.

    step-1.sql
    SELECT TRIM(raw_id) AS customer_id, COUNT(*) AS versions
    FROM bronze_customers
    WHERE raw_id IS NOT NULL
    GROUP BY TRIM(raw_id)
    HAVING COUNT(*) > 1;
  2. Execute a complete script. All setup and the final result run together in one disposable database.

    step-2.sql
    CREATE TEMP TABLE silver_customers AS
    WITH ranked AS(
      SELECT
        *,
        ROW_NUMBER() OVER(PARTITION BY TRIM(raw_id) ORDER BY updated_at DESC) AS rn
      FROM bronze_customers
      WHERE raw_id IS NOT NULL AND TRIM(raw_id)<>''
    )
    SELECT
      TRIM(raw_id) AS customer_id,
      TRIM(name) AS name,
      CASE UPPER(TRIM(country))
        WHEN 'US' THEN 'United States'
        WHEN 'USA' THEN 'United States'
        WHEN 'UK' THEN 'United Kingdom'
        WHEN 'GB' THEN 'United Kingdom'
        WHEN 'IND' THEN 'India'
        WHEN 'CA' THEN 'Canada'
        ELSE UPPER(TRIM(country))
      END AS country
    FROM ranked
    WHERE rn=1;
    SELECT customer_id,name,country
    FROM silver_customers;

challenge 1

Create TEMP silver_customers: trim keys/names; discard NULL/empty keys; keep latest updated_at per trimmed key. Map US/USA→United States, GB/UK→United Kingdom, IND→India, CA→Canada. Return customer_id,name,country.

Return customer_idnamecountryany row ordertable changes are checked too

challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.