Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Data Analysis with Python (pandas, polars, DuckDB)  Module 13 – DuckDB: SQL on DataFrames and files

DuckDB: query CSV, Parquet and JSON files

Query CSV, Parquet and JSON files in place with DuckDB, see what its CSV sniffer guessed and correct it, and compare the three formats for analysis.

  • Intermediate
  • 40 minutes
  • Examples run with Python 3.14.8, pandas 3.0.6, polars 1.44.2 and duckdb 1.5.6
  • By MySmartCoPilot
Free core, Pro depth: 12 of 40 minutes free
Free: One query joins three original file formats · The sniffer separates dialect, type and header · Parquet separates columns and stores statistics · Explicit reader options state the source contract. With a pass: 3 in-depth parts and 3 interview answers, about 28 minutes.

What you will learn

  • Query CSV, Parquet and JSON files in place with read_csv, read_parquet and read_json
  • Diagnose CSV detection with sniff_csv and override delimiters, types and date formats
  • Capture bad rows with store_rejects instead of failing or silently skipping them
  • Read many files at once with globs, file names and Hive partitions

Before you start

For three invoice sources, DuckDB queries data files where they are. SELECT * FROM 'invoices.csv' reads a CSV file as if it were a table, and the same works for Parquet and JSON files, with no import step and no DataFrame in between. Each query reads the file afresh and uses what the file says about itself: a Parquet file stores its column names and types, JSON records are parsed into columns, and for a CSV file a CSV sniffer: A reader process that infers a text table's dialect, column types and header from sampled input. guesses the delimiter, the header and the column types from a sample of rows. When a guess is wrong, read_csv, read_parquet and read_json take options that state the answer instead. This is the quickest way to look at an export before deciding how to load it, to join a file with a table or a DataFrame, and to summarise files larger than the computer’s memory, because DuckDB streams through them.

One query joins three original file formats

A small book distributor keeps its invoice lines in CSV, its catalogue in Parquet and its returns as JSON records, one per line, each with a nested list of returned items:

The CSV and JSON files (catalogue.parquet is binary)

books/invoices.csv

invoice,sold_on,shop,city,sku,qty,amount
INV-101,2026-07-05,Lakshmi Books,Pune,BK-101,4,1800.00
INV-101,2026-07-05,Lakshmi Books,Pune,BK-102,2,598.00
INV-102,2026-07-12,Page Turners,Delhi,BK-103,3,1950.00
INV-103,2026-07-19,Readers Corner,Chennai,BK-101,10,4500.00
INV-104,2026-07-31,Lakshmi Books,Pune,BK-103,1,650.00
INV-105,2026-08-03,Book Nook,Kolkata,BK-102,6,1794.00
INV-105,2026-08-03,Book Nook,Kolkata,BK-104,2,700.00

books/returns.json

{"invoice": "INV-101", "reason": "damaged", "items": [{"sku": "BK-101", "qty": 1}, {"sku": "BK-102", "qty": 1}]}
{"invoice": "INV-105", "reason": "wrong title", "items": [{"sku": "BK-104", "qty": 2}]}
Each file queried in place, then all three in one report Python · books/three_files.py
# Three files, three formats, no loading step: each query reads the files where they are.
import duckdb

print(duckdb.sql("SELECT count(*) AS lines, min(sold_on) AS first, max(sold_on) AS last FROM 'invoices.csv'"))
print(duckdb.sql("SELECT sku, title, publisher, price FROM 'catalogue.parquet' ORDER BY sku"))
print(duckdb.sql("SELECT invoice, reason, len(items) AS skus FROM 'returns.json' ORDER BY invoice"))

# One question across all three: revenue per publisher, less the value of returned copies.
print(duckdb.sql("""
    WITH sold AS (
        SELECT c.publisher, sum(i.amount) AS sold
        FROM 'invoices.csv' AS i JOIN 'catalogue.parquet' AS c USING (sku)
        GROUP BY c.publisher
    ), returned AS (
        SELECT c.publisher, sum(r.item.qty * c.price) AS returned
        FROM (SELECT unnest(items) AS item FROM 'returns.json') AS r
        JOIN 'catalogue.parquet' AS c ON c.sku = r.item.sku
        GROUP BY c.publisher
    )
    SELECT publisher, sold, coalesce(returned, 0) AS returned, sold - coalesce(returned, 0) AS net
    FROM sold LEFT JOIN returned USING (publisher)
    ORDER BY publisher
"""))

Output

┌───────┬────────────┬────────────┐
│ lines │   first    │    last    │
│ int64 │    date    │    date    │
├───────┼────────────┼────────────┤
│     7 │ 2026-07-05 │ 2026-08-03 │
└───────┴────────────┴────────────┘

┌─────────┬────────────────────┬─────────────────┬──────────────┐
│   sku   │       title        │    publisher    │    price     │
│ varchar │      varchar       │     varchar     │ decimal(8,2) │
├─────────┼────────────────────┼─────────────────┼──────────────┤
│ BK-101  │ Monsoon Maths      │ Kavya Press     │       450.00 │
│ BK-102  │ River Stories      │ Kavya Press     │       299.00 │
│ BK-103  │ Data at Dawn       │ Northwind Books │       650.00 │
│ BK-104  │ Hill Station Poems │ Northwind Books │       350.00 │
└─────────┴────────────────────┴─────────────────┴──────────────┘

┌─────────┬─────────────┬───────┐
│ invoice │   reason    │ skus  │
│ varchar │   varchar   │ int64 │
├─────────┼─────────────┼───────┤
│ INV-101 │ damaged     │     2 │
│ INV-105 │ wrong title │     1 │
└─────────┴─────────────┴───────┘

┌─────────────────┬────────┬───────────────┬────────┐
│    publisher    │  sold  │   returned    │  net   │
│     varchar     │ double │ decimal(38,2) │ double │
├─────────────────┼────────┼───────────────┼────────┤
│ Kavya Press     │ 8692.0 │        749.00 │ 7943.0 │
│ Northwind Books │ 3300.0 │        700.00 │ 2600.0 │
└─────────────────┴────────┴───────────────┴────────┘

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 three_files.py

The file names stand in FROM like table names, and DuckDB chooses the reader from the extension. The CSV dates came out as DATE because the sniffer recognised them, the Parquet prices kept the DECIMAL(8,2) type stored in the file, and unnest(items) turned each returned item of the JSON records into a row of its own. The JSON reader also worked out by itself that the file holds one record per line rather than one big list. The report then joins all three: Kavya Press sold 8,692 worth and took back 749, so it nets 7,943. Nothing was copied into a database on the way, so running the script again tomorrow reads tomorrow’s files.

Join the invoice, catalogue and return inputs; reconcile 8,692 sold with 749 returned.

Interactive · stage by stage One query joins three original file formats Step through the original input and compare the stated result with its recorded program.
One query joins three original file formats, step 3 of 3. Showing Input formats, Read and join, Reconcile publisher. In focus: Reconcile publisher.Input formatsCSV,Parquet,JSONRead and joinno import tableReconcile publisher8,692−749=7,943

The drawing shows the whole scene; its 3 steps are listed below.

Every step as text
  1. Invoice lines, the typed catalogue and nested return records remain in their original files.
  2. Each reader exposes the needed rows and types to one SQL report; the JSON item list expands into return lines.
  3. The recorded publisher amount subtracts 749 returned rupees from 8,692 sold rupees, producing net 7,943.

Checkpoint

Check: One query joins three original file formats

  1. Question 1 of 2 Must these files be loaded into a stored database first?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: No; the query can use file readers

    The original report combines readers directly in SQL. Persistent storage is a later choice, not required here.

  2. Question 2 of 2 A publisher sold 8,692 and accepted returns of 749. What net remains?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 7943 rupees

    The recorded subtraction is 8,692−749=7,943 rupees.

The sniffer separates dialect, type and header

A Parquet file describes itself; a CSV file does not, so read_csv works out its layout before reading it:

DuckDB reading a CSV file: sample rows, detect dialect, types and header, read the file; a bad value stops, is skipped or is stored.A CSV fileSample up to 20,480 rowsfrom across the fileDialect: the delimiter, quote andescape that give every row thesame, largest number of columnsTypes: per column, the first ofBOOLEAN, TIME, DATE, TIMESTAMP,BIGINT, DOUBLE that fits everysampled value, else VARCHARHeader: the first row is a headerif its types differ from the rowsbelow itRead the whole file withthese settingsA value that does not fit:stop with an error (default),skip it (ignore_errors), or keepit in reject_errors (store_rejects)Options you pass replace a guess:delim, quote, header, types,dateformat, thousands,decimal_separatorwhile reading

How read_csv decides how to read a CSV file

Text description of the diagram

The diagram is a flow read from top to bottom, with one side box.

  1. It starts with a CSV file.
  2. DuckDB samples up to 20,480 rows from across the file.
  3. It detects the dialect: the delimiter, quote and escape characters that give every sampled row the same, largest number of columns.
  4. It detects each column's type: the first type in the order BOOLEAN, TIME, DATE, TIMESTAMP, BIGINT, DOUBLE that can hold every sampled value, or VARCHAR when none can.
  5. It decides whether the first row is a header: it is one if its values' types differ from the types of the rows below.
  6. It reads the whole file with these settings.
  7. While reading, a value that does not fit its column's type stops the query with an error by default, is skipped with ignore_errors, or is kept in the reject_errors table with store_rejects.

A dashed side box says that options you pass, such as delim, quote, header, types, dateformat, thousands and decimal_separator, replace the matching guess.

The order is the documented one: dialect first, then types, then the header, all from a sample of 20,480 rows by default (CSV auto detection). sniff_csv reports the sampled detection decisions without returning the complete data table:

What the sniffer decided about invoices.csv Python · books/sniff.py
# What DuckDB decided about a CSV file, and the read_csv call that reproduces it.
import textwrap

import duckdb

found = duckdb.sql("SELECT Delimiter, Quote, HasHeader, Columns, DateFormat FROM sniff_csv('invoices.csv')").fetchone()
delimiter, quote, has_header, columns, date_format = found
print("delimiter:", repr(delimiter), "| quote:", repr(quote), "| header:", has_header, "| date format:", date_format)
for col in columns:
    print(f"  {col['name']:<8} {col['type']}")

# Prompt holds the full call with every setting spelled out: paste it into a script to stop guessing.
prompt = duckdb.sql("SELECT Prompt FROM sniff_csv('invoices.csv')").fetchone()[0]
print(textwrap.fill(prompt, 100, subsequent_indent="    "))

Output

delimiter: ',' | quote: '(empty)' | header: True | date format: %Y-%m-%d
  invoice  VARCHAR
  sold_on  DATE
  shop     VARCHAR
  city     VARCHAR
  sku      VARCHAR
  qty      BIGINT
  amount   DOUBLE
FROM read_csv('invoices.csv', auto_detect=false, delim=',', quote='', escape='', new_line='\n',
    skip=0, comment='', header=true, columns={'invoice': 'VARCHAR', 'sold_on': 'DATE', 'shop':
    'VARCHAR', 'city': 'VARCHAR', 'sku': 'VARCHAR', 'qty': 'BIGINT', 'amount': 'DOUBLE'},
    dateformat='%Y-%m-%d');

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 sniff.py

The Prompt column is the most useful part: a read_csv call with every setting spelled out and detection switched off. Pasted into a pipeline, it makes the next run read the file exactly as this one did, instead of guessing again from data that may have changed.

Walk from sampled fields through dialect and types to the reproducible reader call.

Interactive · stage by stage The sniffer separates dialect, type and header Step through the original input and compare the stated result with its recorded program.
The sniffer separates dialect, type and header, step 3 of 3. Showing Sample source, Infer layout, Pin decisions. In focus: Pin decisions.Sample source20,480 rows defaultInfer layoutdialect→types→headerPin decisionsPrompt read_csv call

The drawing shows the whole scene; its 3 steps are listed below.

Every step as text
  1. A sample supplies evidence for the delimiter, quote rules and column types; it is not a guarantee about every later value.
  2. The documented detection order establishes field boundaries before judging types and the header.
  3. The Prompt field gives an explicit read_csv call that can repeat the detected settings with guessing switched off.

Checkpoint

Check: The sniffer separates dialect, type and header

  1. Question 1 of 2 What does the Prompt field provide?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: An explicit reader call with detected settings

    Prompt records the inferred reading configuration. Rejected-line auditing belongs to the later load, not that configuration text.

  2. Question 2 of 2 The sniffer shows seven original invoice columns. How many column types are listed?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 7 columns

    The invoice schema lists one type for each of its seven fields.

Parquet separates columns and stores statistics

The three formats as DuckDB reads them
Criterion CSVParquetJSON
Where the columns and types come from Guessed from a sample of rowsStored in the fileInferred from the records
Reads only the columns a query needs No: every line is parsedYes: each column is stored apartNo: every record is parsed
Can skip data a filter excludes NoYes, using per-group minimum and maximum valuesNo
Nested lists and objects Not supportedSupportedSupported, and common
When to choose Hand-offs, exports and spreadsheetsStoring data for analysisData from APIs, logs and event streams

CSV is a common hand-off format, but parsing and type inference add work and can misread source conventions. Its cost relative to other formats depends on the data, query and physical layout. Parquet is the format to keep data in for analysis: it stores types exactly, compresses well, and lets DuckDB read only the columns and row groups a query needs. JSON sits between them: it keeps nesting that CSV cannot express, but every record has to be parsed.

Compare record parsing with column chunks and ask which ranges the predicate can exclude.

Interactive · stage by stage Parquet separates columns and stores statistics Step through the original input and compare the stated result with its recorded program.
Parquet separates columns and stores statistics, step 3 of 3. Showing Text formats, Columnar format, Filter with metadata. In focus: Filter with metadata.Text formatsparse record fieldsColumnar formattyped column chunksFilter with metadatarow-group ranges

The drawing shows the whole scene; its 3 steps are listed below.

Every step as text
  1. CSV and JSON need the record structure read to find the requested fields; JSON can additionally represent nesting.
  2. Parquet stores typed column data separately, enabling a projection to avoid unneeded chunks.
  3. A predicate can reject a group whose stored bounds exclude the requested value; actual selectivity and layout determine what is skipped.

Checkpoint

Check: Parquet separates columns and stores statistics

  1. Question 1 of 2 Which original format permits reading one stored column chunk?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Parquet

    The columnar layout stores columns separately. A CSV header names fields but does not separate their bytes into column chunks.

  2. Question 2 of 2 A ten-column file needs four columns. How many are not needed by that projection?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 6 columns

    Ten total columns minus four requested columns leaves six unneeded columns.

Explicit reader options state the source contract

Real exports break the guesses in a handful of ways, and each has an option or a function that settles it:

  • delim, header and types state the delimiter, whether there is a header row, and the type of any column.
  • dateformat and timestampformat say how dates are written, such as %d/%m/%Y for day-first dates.
  • thousands and decimal_separator read numbers such as 1,234,567.50 or 1.234,50 as numbers.
  • reject record: An audit entry identifying a row whose attempted conversion failed, with its location and error. sets each line that fails aside in a table, with its line number and error, while the rest load.
  • ignore_errors skips failing lines silently, which is why a report should prefer store_rejects.
  • sample_size sets how many rows the sniffer samples; -1 samples the whole file.
  • A glob such as 'monthly/*.csv' reads many files as one table, and schema union by name: A combined table schema that aligns fields by their names and fills absent fields with missing values. lines their columns up by name.
  • Hive partition: A dataset folder whose key=value path segments identify partition values used while reading its files. turns folder names such as city=Pune into columns that filters can use to skip files.
  • encoding reads Latin-1 and UTF-16 files; UTF-8 is the default.
  • parquet_metadata() lists a Parquet file’s row groups and each column’s minimum and maximum, without reading rows.
  • read_json turns records into rows and nested lists into list columns, which unnest expands into rows.

Choose the reader setting that states each known source convention.

Interactive · stage by stage Explicit reader options state the source contract Step through the original input and compare the stated result with its recorded program.
Explicit reader options state the source contract, step 3 of 3. Showing Know the source, Read deliberately, Many files. In focus: Many files.Know the sourcedelimiter,types,datesRead deliberatelyrecord bad linesMany filesnames and partitions

The drawing shows the whole scene; its 3 steps are listed below.

Every step as text
  1. The source convention determines its delimiter, date format, numeric grouping and required types.
  2. A scheduled load can stop on malformed data or retain reject details; the choice must be explicit.
  3. Named schema alignment and partition values make a folder query's structure inspectable instead of assuming every export matches.

Checkpoint

Check: Explicit reader options state the source contract

  1. Question 1 of 2 What should replace a known wrong date-format guess?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The source's explicit dateformat

    The source convention supplies the intended interpretation. Repeating the same guess does not establish that interpretation.

  2. Question 2 of 2 Three source dialects each need one explicit configuration. How many configurations are needed?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 3 sources

    One stated configuration per source gives three configurations.

Messy CSV files: overrides, regional number formats and rejected lines Pro: opens with a Pro, Premium or Ultimate pass

Exports from tills, banks and older systems break the sniffer’s guesses in predictable ways. This part reads such a file correctly, reproduces the traps of dates, sampling and rejects, and ends with an exercise that loads a folder of branch exports with a report of every line set aside.

In this part:

  • Types and numeric separators recover four valid rows
  • A successful parse can use the wrong day convention
  • Projection can avoid converting the bad date
  • One dialect per branch yields eight audited invoices

4 diagrams · 6 runnable examples (CSV, Python) · about 9 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Many files in one query: globs, schema drift and Hive partitions Pro: opens with a Pro, Premium or Ultimate pass

A folder of exports is one table to an analyst and many files to DuckDB. This part shows which columns a glob produces when the files disagree, and how Hive-style folder names let a filter skip files without opening them.

In this part:

  • Name alignment preserves added and renamed fields
  • Path values let a filter skip seven files

2 diagrams · 3 runnable examples (Python) · about 5 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Parquet and JSON in depth: row groups, measured speed and nested records Pro: opens with a Pro, Premium or Ultimate pass

Parquet is fast for reasons you can inspect, and JSON is flexible in ways that break strict schemas. This part reads a Parquet file’s statistics, measures CSV against Parquet on a million rows, and flattens JSON whose shape varies from record to record.

In this part:

  • Sorted groups make one range relevant
  • Measured: the same million rows as CSV and as Parquet
  • A mixed JSON item shape needs a stated normalization

2 diagrams · 3 runnable examples (Python) · about 5 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Practise the stated query contracts

Practice that adapts to you

Practise this lesson

9 questions about 12 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 9 A publisher sells 9,100 rupees and receives 650 rupees in returns. What net remains?

    Type a number.

    Show the answer: Question 1 of 9

    Answer: 8450 rupees

    Net revenue is 9,100−650=8,450 rupees.

  2. Question 2 of 9 A source has five named fields. How many column types should its explicit reader configuration state?

    Type a number.

    Show the answer: Question 2 of 9

    Answer: 5 columns

    One type for each of the five source fields gives five declared types.

  3. Question 3 of 9 A twelve-column file needs three columns. How many are outside that projection?

    Type a number.

    Show the answer: Question 3 of 9

    Answer: 9 columns

    Twelve total columns minus three requested columns leaves nine unneeded columns.

  4. Question 4 of 9 Four branches each need a stated source dialect. How many configurations identify them?

    Type a number.

    Show the answer: Question 4 of 9

    Answer: 4 sources

    One declared configuration per branch gives four source configurations.

  5. Question 5 of 9 Which sequence matches the documented CSV detection process?

    Choose one answer.

    Show the answer: Question 5 of 9

    Answer: Sample rows, detect dialect, detect types, decide the header

    The sniffer samples up to 20,480 rows, finds the dialect that gives every row the same, largest number of columns, then the types, and only then decides on the header, by checking whether the first row's types differ from the rows below.

  6. Question 6 of 9 What does the Prompt column of sniff_csv give you?

    Choose one answer.

    Show the answer: Question 6 of 9

    Answer: A read_csv call with every detected setting spelled out and detection switched off

    Prompt repeats the sniffer's decisions as an explicit read_csv call with auto_detect=false, so a pipeline can read the file the same way on every run instead of guessing again.

  7. Question 7 of 9 A query sums one column of a wide table. Which format lets DuckDB read only that column from disk?

    Choose one answer.

    Show the answer: Question 7 of 9

    Answer: Parquet, which stores each column separately

    A Parquet file stores each column apart, with statistics per row group, so DuckDB reads only the columns and groups a query needs. A CSV or JSON reader has to parse every line or record to find the field.

  8. Question 8 of 9 A file writes amounts as "1.234,50" (one thousand two hundred thirty-four and a half). Which options read them as numbers?

    Choose one answer.

    Show the answer: Question 8 of 9

    Answer: decimal_separator = ',' and thousands = '.'

    decimal_separator names the character before the fraction and thousands the grouping character; they must differ. delim is the column separator, which has nothing to do with the numbers inside a field.

  9. Question 9 of 9 A nightly load must keep going when a line is broken, but someone must be able to see which lines were left out. Which option fits?

    Choose one answer.

    Show the answer: Question 9 of 9

    Answer: store_rejects = true, which keeps each failing line in a rejects table

    ignore_errors skips the line without a trace. store_rejects skips it too, but records its line number, column, error type and original text in reject_errors, which a report or an alert can read.

Interview questions

  1. Fresher to mid · Warm-up

    What does DuckDB's CSV sniffer decide about a file, and when should you stop relying on it?

    From a sample of up to 20,480 rows, the sniffer decides the dialect (the delimiter, quote and escape characters), the type of each column, and whether the first row is a header. sniff_csv shows those decisions, and its Prompt column is the equivalent read_csv call with detection switched off. Rely on it to look at a file you have never seen. Stop relying on it once the file feeds a scheduled job or a report: a value outside the sample can change a column's type or fail the read, and dates that fit both day-first and month-first are read day-first. From then on, state the delimiter, the header, the date format and the types, for example by pasting the Prompt into the pipeline.

  2. Fresher to mid

    A vendor's monthly CSV has loaded cleanly for six months. In month seven, the revenue query fails because amount is suddenly VARCHAR, though nothing in your code changed. How do you find the cause, and how do you make the load robust?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Mid to senior

    Every morning a job reads 900 daily CSV files, about 40 GB, with one read_csv glob, and keeps only the last seven days for a dashboard. It now takes 25 minutes. What do you check first, and how do you make it fast?

    Model answer, Pro. First step and follow-ups

  4. Mid to senior

    A partner's JSON export has an items field that is a list of objects in most records, a single object in some, and missing or null in a few. Design a DuckDB load that gives one row per item, and say how you would notice a new shape next month.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • FROM 'file.csv', 'file.parquet' and 'file.json' read files in place; read_csv, read_parquet and read_json take options when the defaults are wrong.
  • The CSV sniffer detects the dialect, the types and the header from a sample. sniff_csv shows its decisions, and its Prompt is a read_csv call that repeats them without guessing.
  • Parquet stores types and statistics and lets DuckDB read only the columns a query needs; CSV is text to be parsed and guessed; JSON keeps nesting.
  • store_rejects sets failing lines aside in a table with their line numbers, where ignore_errors hides them.

Terms in this lesson

CSV sniffer
A reader process that infers a text table's dialect, column types and header from sampled input.
Hive partition
A dataset folder whose key=value path segments identify partition values used while reading its files.
Parquet row group
A horizontal group of rows stored as separate column chunks, usually with statistics for each chunk.
reject record
An audit entry identifying a row whose attempted conversion failed, with its location and error.
schema union by name
A combined table schema that aligns fields by their names and fills absent fields with missing values.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.