Skip to main content

Job postings

200,000 job postings for data roles, each with the full description text. Three short columns to group and filter on, one long text column to classify. That makes it the dataset the AI function examples in these docs run against.

Explore the data​

This Dive pages through the postings and answers typed questions about each one with prompt_jev — is this a data role, which role family, what seniority, does it state a salary, does it manage people. Ask your own yes/no question in the box and the page re-sorts by how well each posting matches.

Loading live Dive preview...

About the dataset​

Postings199,999
Listed between2025-01-01 and 2026-08-23
Locations3,129
Average description length4,316 characters
Files20 Parquet files, one per listing month, ZSTD, 231 MB total

Every posting is for a data role. Titles were filtered on terms like analyst, analytics, data, BI, ML, engineer, and the common tool names, so the corpus is dense in one domain rather than spread thin across every job on the market. Duplicate postings are removed: one row per posting, keyed on job_id.

The dataset keeps the posting, not the poster. There is no employer column, no URLs, no applicant or engagement counts, and no company profile fields — only the five columns below. Descriptions are unedited, so many of them still name the employer in the body text.

How to query the dataset​

The files are public and need no credentials. Use the s3:// path to read the whole corpus, because a glob needs a directory listing and plain HTTPS has none:

Ten job postings
SELECT listed_date, title, location
FROM read_parquet('s3://us-prd-motherduck-open-datasets/job_postings/parquet/year=*/month=*/jobs.parquet')
ORDER BY listed_date DESC, job_id
LIMIT 10;
SQL Editor loading...
Login to connect

The files are laid out in Hive-style folders, so a year and month filter reads only the months it needs:

Read one month with Hive partitioning
SELECT
  count(*)
FROM
  read_parquet(
    's3://us-prd-motherduck-open-datasets/job_postings/parquet/year=*/month=*/jobs.parquet',
    hive_partitioning = TRUE
  )
WHERE
  year = 2026
  AND month = '03';
SQL Editor loading...
Login to connect

A single month is one file, about 10 MB, and that one you can read straight over HTTPS:

Read a single month over HTTPS
SELECT
  *
FROM
  'https://us.data.motherduck.com/job_postings/parquet/year=2026/month=03/jobs.parquet';
SQL Editor loading...
Login to connect

To query it repeatedly, load it into your own database once. The description column is the expensive part of every scan:

Load the full corpus into your own database
CREATE TABLE my_db.job_postings AS
SELECT *
FROM read_parquet('s3://us-prd-motherduck-open-datasets/job_postings/parquet/year=*/month=*/jobs.parquet');
SQL Editor loading...
Login to connect
tip

Parquet reads only the columns a query names. SELECT title, location over all 20 files touches a few megabytes; adding description touches all 231 MB. Leave the description out until a query needs it.

Example queries​

Where the roles are​

Top locations by postings
SELECT location, count(*) AS postings
FROM read_parquet('s3://us-prd-motherduck-open-datasets/job_postings/parquet/year=*/month=*/jobs.parquet')
GROUP BY location
ORDER BY postings DESC
LIMIT 8;
SQL Editor loading...
Login to connect
PreviewLogin for live results

location is free text as the employer typed it, so London appears twice under two spellings. Normalizing it is its own exercise, and a reasonable first use of prompt_jev on this data.

Hiring volume over time​

Hiring volume over time
SELECT
  date_trunc('quarter', listed_date) AS quarter,
  count(*) AS postings
FROM read_parquet('s3://us-prd-motherduck-open-datasets/job_postings/parquet/year=*/month=*/jobs.parquet')
GROUP BY quarter
ORDER BY quarter;
SQL Editor loading...
Login to connect
PreviewLogin for live results

The last quarter is partial: collection stops on 2026-08-23.

Which postings mention a tool​

The description is free text, so a keyword search finds mentions but not meaning. ilike catches "we use dbt" and "no dbt experience needed" alike:

Which postings mention a tool
SELECT
  count(*) FILTER (description ILIKE '%dbt%') AS mentions_dbt,
  count(*) FILTER (description ILIKE '%airflow%') AS mentions_airflow,
  count(*) FILTER (description ILIKE '%duckdb%') AS mentions_duckdb,
  count(*) AS postings
FROM read_parquet('s3://us-prd-motherduck-open-datasets/job_postings/parquet/year=*/month=*/jobs.parquet');
SQL Editor loading...
Login to connect
PreviewLogin for live results

To separate a requirement from a passing mention, ask the model instead of the string. See Classify text with prompt_jev.

Schema​

job_postings​

column_namecolumn_typedescription
job_idVARCHARUnique per posting. Use it as the join key for anything you derive.
listed_dateDATEThe day the posting went up.
titleVARCHARJob title as posted.
locationVARCHARLocation as posted, free text: "London Area, United Kingdom", "Menlo Park, CA".
descriptionVARCHARThe full posting body, 4,316 characters on average.

year and month come from the folder names when you read with hive_partitioning = true. month is a zero-padded VARCHAR, so compare it as month = '03'.

Rows have no guaranteed order. Sort with ORDER BY listed_date DESC, job_id whenever order matters.