Den här sidan visar hur man gör varje moment i uppgiften i terminalen, med små exempel.
Det här är fusklappar. Försök själv först, med dokumentationen och
DESCRIBE/SUMMARIZE som stöd. Kika här bara när du kört fast.
1. Titta innan du gissar
DuckDB läser en CSV som om den vore en tabell. Ingen import behövs:
duckdb -c "SELECT * FROM 'data/job_skills.csv' LIMIT 5"Kolumnerna och typerna DuckDB gissade sig till:
duckdb -c "DESCRIBE SELECT * FROM 'data/job_skills.csv'"SUMMARIZE ger min, max, antal unika och andel null per kolumn. Det är det
snabbaste sättet att hitta det som är stökigt:
duckdb -c "SUMMARIZE SELECT * FROM 'data/people_skills.csv'"Titta särskilt på kolumner som är VARCHAR men egentligen är något annat:
en lista, ett JSON-dokument, ett datum.
2. Spara arbetet i en fil
Öppna en databas på disk så finns tabellerna kvar mellan körningar, och kan
öppnas i webgränssnittet (duckdb -ui hack.db) och från Python:
duckdb hack.dbCREATE TABLE jobs AS SELECT * FROM 'data/job_skills.csv';
CREATE TABLE people AS SELECT * FROM 'data/people_skills.csv';
SHOW TABLES;CREATE OR REPLACE TABLE är praktiskt när du itererar på en fråga.
Bra att kunna i CLI:t: .tables, .mode line (en kolumn per rad, bra för
breda tabeller), .mode duckbox (tillbaka till standard), .quit.
3. En sträng med kommatecken är en lista
skills ser ut så här: "python, sql, azure". Tre funktioner räcker:
SELECT string_split('python, sql, azure', ','); -- [python, sql, azure]
SELECT unnest(string_split('python, sql, azure', ',')); -- en rad per element
SELECT trim(unnest(string_split('python, sql, azure', ','))); -- utan mellanslagKör dem en i taget och titta på vad som händer med resultatet. unnest gör
en lista till rader, och de andra kolumnerna i SELECT följer med på varje
rad. Det är exakt det som behövs för att gå från en rad per uppdrag till en
rad per uppdrag och skill.
Din uppgift: gör en tabell job_skill med kolumnerna job_id, skill, och
en person_skill på samma sätt. SELECT DISTINCT tar bort dubbletter.
Kontrollera med count(*) att antalet rader är rimligt.
4. JSON i en sträng
skills_detailed i people är en JSON-lista med nivå per skill. DuckDB kan
parsa den, och ->> plockar ut ett fält som text:
SELECT s ->> 'skill_name' AS skill, (s ->> 'level')::INT AS level
FROM unnest(from_json('[{"skill_name":"sql","level":4}]', '["json"]')) AS t(s);Byt ut den hårdkodade strängen mot kolumnen och lägg till FROM people
före unnest-delen (samma mönster som i steg 3), så har du nivå per person
och skill. Dokumentation: https://duckdb.org/docs/stable/data/json/overview
5. Städa namn
Räkna först. Sorterat efter antal syns dubbletterna direkt:
SELECT skill, count(*) AS n
FROM job_skill
GROUP BY skill
ORDER BY n DESC;Sök sedan efter varianter av samma sak:
SELECT DISTINCT skill FROM job_skill WHERE skill ILIKE '%azure%';Det finns inget rätt svar på om "azure devops" är "azure". Men det finns ett
bra sätt att uttrycka beslutet: en tabell skill som mappar råa namn till
ett kanoniskt, som du sedan joinar mot.
CREATE TABLE skill (raw VARCHAR, name VARCHAR);
INSERT INTO skill VALUES ('microsoft azure', 'azure'), ('azure', 'azure');Verktyg att fylla den med: lower(), trim(), replace(), CASE WHEN ... ILIKE, och för det luddiga jaro_winkler_similarity(a, b) som ger ett tal
0–1 för hur lika två strängar är. Allt som inte finns i skill-tabellen
kan få behålla sitt råa namn (coalesce).
Funktioner: https://duckdb.org/docs/stable/sql/functions/text
6. Joina och räkna
När job_skill, person_skill och skill finns är analysfrågorna vanlig
SQL: JOIN, GROUP BY, count(*). Två saker att ha koll på:
dateär text i CSV:n.date_trunc('month', date::TIMESTAMP)ger en kolumn att gruppera per månad på.- Ett gap mellan marknad och team är en skill som finns i den ena tabellen
men inte i den andra:
LEFT JOIN ... WHERE ... IS NULL, ellerEXCEPT.
7. Spara ut resultatet
COPY person_skill TO 'output/person_skill.parquet';
COPY (SELECT ...) TO 'output/top_skills.csv';Parquet-filen kan läsas tillbaka med SELECT * FROM 'output/person_skill.parquet',
från vilken maskin som helst.