René's URL Explorer Experiment


Title: Joining Data (Video) – Real Python

Open Graph Title: Joining Data – Real Python

Description: In the previous lesson, I showed you how to programmatically access the data in a relation object. In this lesson, I’ll be querying data across multiple tables with an SQL join. A SELECT statement can build a result set by querying across multiple…

Open Graph Description: In the previous lesson, I showed you how to programmatically access the data in a relation object. In this lesson, I’ll be querying data across multiple tables with an SQL join. A SELECT statement can build a result set by querying across multiple…

Opengraph URL: https://realpython.com/lessons/duckdb-joining-data/

X: @realpython

direct link

Domain: realpython.com


Hey, it has json ld scripts:
  {
    "@context": "https://schema.org",
    "@type": "VideoObject",
    "name": "Joining Data",
    "description": "In the previous lesson, I showed you how to programmatically access the data in a relation object. In this lesson, I’ll be querying data across multiple tables with an SQL join. A SELECT statement can build a result set by querying across multiple…",
    "thumbnailUrl": ["https://files.realpython.com/media/Showcase-DuckDB_Watermarked.4ff6c6a498a1.jpg"],
    "uploadDate": "2025-06-24T14:00:00+00:00",
    "duration": "PT9M39S",
    
    "potentialAction": {
      "@type": "SeekToAction",
      "target": "https://realpython.com/lessons/duckdb-joining-data/#t={seek_to_second_number}",
      "startOffset-input": "required name=seek_to_second_number"
    }
  }
  

authorReal Python
twitter:cardsummary_large_image
twitter:imagehttps://files.realpython.com/media/Showcase-DuckDB_Watermarked.4ff6c6a498a1.jpg
og:imagehttps://files.realpython.com/media/Showcase-DuckDB_Watermarked.4ff6c6a498a1.jpg
twitter:creator@realpython
og:typevideo.episode

Links:

https://realpython.com/
Start Herehttps://realpython.com/start-here/
Learn Python https://realpython.com/lessons/duckdb-joining-data/
Python Tutorials →In-depth articles and video courseshttps://realpython.com/search?kind=article&kind=course&order=newest
Learning Paths →Guided study plans for accelerated learninghttps://realpython.com/learning-paths/
Quizzes & Exercises →Check your learning progresshttps://realpython.com/quizzes/
Browse Topics →Focus on a specific area or skill levelhttps://realpython.com/tutorials/all/
Community Chat →Learn with other Pythonistashttps://realpython.com/community/
Office Hours →Live Q&A calls with Python expertshttps://realpython.com/office-hours/
Podcast →Hear what’s new in the world of Pythonhttps://realpython.com/podcasts/rpp/
Books →Round out your knowledge and learn offlinehttps://realpython.com/products/books/
Reference →Concise definitions for common Python termshttps://realpython.com/ref/
Code Mentor →BetaPersonalized code assistance & learning toolshttps://realpython.com/mentor/
Unlock All Content →https://realpython.com/account/join/
More https://realpython.com/lessons/duckdb-joining-data/
Learner Storieshttps://realpython.com/learner-stories/
Python Newsletterhttps://realpython.com/newsletter/
Python Job Boardhttps://www.pythonjobshq.com
Meet the Teamhttps://realpython.com/team/
Become a Contributorhttps://realpython.com/jobs/
Searchhttps://realpython.com/search
https://realpython.com/search
Joinhttps://realpython.com/account/join/
Sign‑Inhttps://realpython.com/account/login/?next=%2Flessons%2Fduckdb-joining-data%2F
Unlock This Lessonhttps://realpython.com/account/join/?utm_source=rp_lesson&utm_content=starting-duckdb-python
Unlock This Lessonhttps://realpython.com/account/join/?utm_source=rp_lesson&utm_content=starting-duckdb-python
https://realpython.com/courses/starting-duckdb-python/#team
Starting With DuckDB and Pythonhttps://realpython.com/courses/starting-duckdb-python/
Christopher Trudeauhttps://realpython.com/courses/starting-duckdb-python/#team
Recommended Tutorialhttps://realpython.com/python-duckdb/
Course Slides (.pdf)https://realpython.com/courses/starting-duckdb-python/downloads/duckdb-slides/
Sample Code (.zip)https://realpython.com/courses/starting-duckdb-python/downloads/duckdb-code/
Ask a Questionhttps://realpython.com/lessons/duckdb-joining-data/#discussion
https://realpython.com/feedback/survey/course/starting-duckdb-python/liked/?from=lesson-title
https://realpython.com/feedback/survey/course/starting-duckdb-python/disliked/?from=lesson-title
Transcripthttps://realpython.com/lessons/duckdb-joining-data/#transcript
Discussionhttps://realpython.com/lessons/duckdb-joining-data/#discussion
00:00https://realpython.com/lessons/duckdb-joining-data/#t=0.535
In the previous lesson, I showed you howhttps://realpython.com/lessons/duckdb-joining-data/#t=0.535
to programmatically access the data in a relation object.https://realpython.com/lessons/duckdb-joining-data/#t=2.195
In this lesson, I’ll be querying data across multiple tableshttps://realpython.com/lessons/duckdb-joining-data/#t=5.215
with an SQL join.https://realpython.com/lessons/duckdb-joining-data/#t=8.235
00:11https://realpython.com/lessons/duckdb-joining-data/#t=11.095
A SELECT statement can build a result sethttps://realpython.com/lessons/duckdb-joining-data/#t=11.095
by querying across multiple tables.https://realpython.com/lessons/duckdb-joining-data/#t=13.635
This is known as a JOIN.https://realpython.com/lessons/duckdb-joining-data/#t=16.045
When you add a JOIN to a SELECT statement, you needhttps://realpython.com/lessons/duckdb-joining-data/#t=18.085
to specify which tables are participating in the join,https://realpython.com/lessons/duckdb-joining-data/#t=20.855
and what conditionhttps://realpython.com/lessons/duckdb-joining-data/#t=24.115
or conditions to use to relate the rows between the tables.https://realpython.com/lessons/duckdb-joining-data/#t=25.275
00:29https://realpython.com/lessons/duckdb-joining-data/#t=29.905
This mechanism is often used to express onehttps://realpython.com/lessons/duckdb-joining-data/#t=29.905
-to-many relationships in your data.https://realpython.com/lessons/duckdb-joining-data/#t=32.675
For example, a book can have multiple authors.https://realpython.com/lessons/duckdb-joining-data/#t=35.305
If you have a book table with an author column,https://realpython.com/lessons/duckdb-joining-data/#t=38.625
you wouldn’t be able to express this.https://realpython.com/lessons/duckdb-joining-data/#t=40.945
00:42https://realpython.com/lessons/duckdb-joining-data/#t=42.735
You’d be stuck with however many author columns you had.https://realpython.com/lessons/duckdb-joining-data/#t=42.735
You could have three author columns,https://realpython.com/lessons/duckdb-joining-data/#t=46.065
but what if the book has four authors?https://realpython.com/lessons/duckdb-joining-data/#t=47.665
Also, what if you wanthttps://realpython.com/lessons/duckdb-joining-data/#t=50.395
to store more information about the author. Instead,https://realpython.com/lessons/duckdb-joining-data/#t=51.645
the structure you use in this case is a table for bookshttps://realpython.com/lessons/duckdb-joining-data/#t=54.745
with each book having a unique ID,https://realpython.com/lessons/duckdb-joining-data/#t=58.315
and a table for authors, who also get their own ID.https://realpython.com/lessons/duckdb-joining-data/#t=60.545
01:04https://realpython.com/lessons/duckdb-joining-data/#t=64.585
By having separate tables, you can have all sortshttps://realpython.com/lessons/duckdb-joining-data/#t=64.585
of information that are specific to each thing.https://realpython.com/lessons/duckdb-joining-data/#t=66.805
The ISBN number could go with the book,https://realpython.com/lessons/duckdb-joining-data/#t=69.745
while the date of birth could go with the author.https://realpython.com/lessons/duckdb-joining-data/#t=72.115
01:15https://realpython.com/lessons/duckdb-joining-data/#t=75.375
To express the relationship between a book and its authors,https://realpython.com/lessons/duckdb-joining-data/#t=75.375
you would then need a third table.https://realpython.com/lessons/duckdb-joining-data/#t=78.375
This table would contain a column for a book’s IDhttps://realpython.com/lessons/duckdb-joining-data/#t=80.785
and a column for an author’s ID.https://realpython.com/lessons/duckdb-joining-data/#t=83.495
01:26https://realpython.com/lessons/duckdb-joining-data/#t=86.075
A book with multiple authors would be expressedhttps://realpython.com/lessons/duckdb-joining-data/#t=86.075
by multiple rows in this relationship table, onehttps://realpython.com/lessons/duckdb-joining-data/#t=88.215
for each book-author pair.https://realpython.com/lessons/duckdb-joining-data/#t=91.155
With this kind of table structure in place,https://realpython.com/lessons/duckdb-joining-data/#t=93.945
you would use a join operationhttps://realpython.com/lessons/duckdb-joining-data/#t=96.095
to query which authors are associatedhttps://realpython.com/lessons/duckdb-joining-data/#t=97.755
with any given book or books.https://realpython.com/lessons/duckdb-joining-data/#t=100.225
01:44https://realpython.com/lessons/duckdb-joining-data/#t=104.695
Although the three-table structurehttps://realpython.com/lessons/duckdb-joining-data/#t=104.695
that I just mentioned is common, it’s a little complex,https://realpython.com/lessons/duckdb-joining-data/#t=106.055
so I’m going to use a slightly simpler example.https://realpython.com/lessons/duckdb-joining-data/#t=108.715
On screen here is a simplified versionhttps://realpython.com/lessons/duckdb-joining-data/#t=111.395
of our presidents data, along with a new tablehttps://realpython.com/lessons/duckdb-joining-data/#t=113.875
that contains the political parties information.https://realpython.com/lessons/duckdb-joining-data/#t=116.765
02:00https://realpython.com/lessons/duckdb-joining-data/#t=120.205
You may recall that our president table had a columnhttps://realpython.com/lessons/duckdb-joining-data/#t=120.205
called party_id.https://realpython.com/lessons/duckdb-joining-data/#t=123.025
The party table then has a column which useshttps://realpython.com/lessons/duckdb-joining-data/#t=125.045
that same identifier. To query the presidenthttps://realpython.com/lessons/duckdb-joining-data/#t=127.745
and their party name, you need a join.https://realpython.com/lessons/duckdb-joining-data/#t=130.965
02:17https://realpython.com/lessons/duckdb-joining-data/#t=137.465
The SELECT portion is similar to what you’ve seen before.https://realpython.com/lessons/duckdb-joining-data/#t=137.465
Just note that the columns in the SELECT can be from anyhttps://realpython.com/lessons/duckdb-joining-data/#t=140.795
of the tables participating in the join.https://realpython.com/lessons/duckdb-joining-data/#t=143.965
02:28https://realpython.com/lessons/duckdb-joining-data/#t=148.035
After the JOIN keyword,https://realpython.com/lessons/duckdb-joining-data/#t=148.035
you provide the other tables participating.https://realpython.com/lessons/duckdb-joining-data/#t=150.085
In this case, it’s the parties table.https://realpython.com/lessons/duckdb-joining-data/#t=152.445
The ON keyword dictates how to relate the datahttps://realpython.com/lessons/duckdb-joining-data/#t=154.765
between the two tables.https://realpython.com/lessons/duckdb-joining-data/#t=159.115
02:41https://realpython.com/lessons/duckdb-joining-data/#t=161.135
In our case, the party_id is common between them,https://realpython.com/lessons/duckdb-joining-data/#t=161.135
so when the party_id on presidents matches the party_id onhttps://realpython.com/lessons/duckdb-joining-data/#t=164.215
the party’s table, the data gets joined.https://realpython.com/lessons/duckdb-joining-data/#t=168.015
02:51https://realpython.com/lessons/duckdb-joining-data/#t=171.275
The resulting data is each president with the namehttps://realpython.com/lessons/duckdb-joining-data/#t=171.275
of their party. Joins can gethttps://realpython.com/lessons/duckdb-joining-data/#t=173.775
much more complicated than this,https://realpython.com/lessons/duckdb-joining-data/#t=176.295
having more than two tables as well as different ruleshttps://realpython.com/lessons/duckdb-joining-data/#t=177.455
for how to match datahttps://realpython.com/lessons/duckdb-joining-data/#t=180.025
on the left to data on the right,https://realpython.com/lessons/duckdb-joining-data/#t=181.105
this is really just a taste,https://realpython.com/lessons/duckdb-joining-data/#t=183.115
a tiny little breadcrumb tossed in a pond.https://realpython.com/lessons/duckdb-joining-data/#t=185.365
03:08https://realpython.com/lessons/duckdb-joining-data/#t=188.735
Let’s go see this in practice. Same import, same data,https://realpython.com/lessons/duckdb-joining-data/#t=188.735
03:18https://realpython.com/lessons/duckdb-joining-data/#t=198.305
and a quick query to remind you what’s in there.https://realpython.com/lessons/duckdb-joining-data/#t=198.305
You may recall from a previous lesson,https://realpython.com/lessons/duckdb-joining-data/#t=201.065
I used the limit method to restricthttps://realpython.com/lessons/duckdb-joining-data/#t=203.205
how many rows got shown in the result.https://realpython.com/lessons/duckdb-joining-data/#t=205.105
03:27https://realpython.com/lessons/duckdb-joining-data/#t=207.425
The reason it’s called LIMIT rather than HEAD, ishttps://realpython.com/lessons/duckdb-joining-data/#t=207.425
because LIMIT is an SQL keyword.https://realpython.com/lessons/duckdb-joining-data/#t=210.245
I’ve used it in my query herehttps://realpython.com/lessons/duckdb-joining-data/#t=212.675
to return just the first two results.https://realpython.com/lessons/duckdb-joining-data/#t=214.185
03:36https://realpython.com/lessons/duckdb-joining-data/#t=216.735
Alright, that’s our presidents data.https://realpython.com/lessons/duckdb-joining-data/#t=216.735
Now let’s go get the party info.https://realpython.com/lessons/duckdb-joining-data/#t=218.845
03:45https://realpython.com/lessons/duckdb-joining-data/#t=225.555
Parquet and CSV arehttps://realpython.com/lessons/duckdb-joining-data/#t=225.555
so 10 minutes ago. This time the data’s in JSON. Note,https://realpython.com/lessons/duckdb-joining-data/#t=227.305
I’ve chained the to_table() call here on the end.https://realpython.com/lessons/duckdb-joining-data/#t=231.075
03:59https://realpython.com/lessons/duckdb-joining-data/#t=239.195
So far, so familiar. Okay, how about a quick sanity check?https://realpython.com/lessons/duckdb-joining-data/#t=239.195
How do you know what’s in your database?https://realpython.com/lessons/duckdb-joining-data/#t=243.635
Well, the database itself contains metadata about thehttps://realpython.com/lessons/duckdb-joining-data/#t=245.645
database, which you can query.https://realpython.com/lessons/duckdb-joining-data/#t=248.775
04:15https://realpython.com/lessons/duckdb-joining-data/#t=255.435
The special duckdb_tables table tells us there are twohttps://realpython.com/lessons/duckdb-joining-data/#t=255.435
tables in the database.https://realpython.com/lessons/duckdb-joining-data/#t=259.755
Okay, let’s construct our join.https://realpython.com/lessons/duckdb-joining-data/#t=262.005
04:37https://realpython.com/lessons/duckdb-joining-data/#t=277.925
So far, this is just like the example I showed you.https://realpython.com/lessons/duckdb-joining-data/#t=277.925
Let’s add a little orange glaze to our duck.https://realpython.com/lessons/duckdb-joining-data/#t=280.355
04:45https://realpython.com/lessons/duckdb-joining-data/#t=285.995
Rather than seeing everyone, I’ve restricted the resultshttps://realpython.com/lessons/duckdb-joining-data/#t=285.995
to just the Whig party.https://realpython.com/lessons/duckdb-joining-data/#t=289.395
This could also have been donehttps://realpython.com/lessons/duckdb-joining-data/#t=291.355
with the party_id on either table if you knew thehttps://realpython.com/lessons/duckdb-joining-data/#t=292.685
ID for the Whigs.https://realpython.com/lessons/duckdb-joining-data/#t=296.305
05:00https://realpython.com/lessons/duckdb-joining-data/#t=300.365
The ORDER BY clause specifies the sorting of the results.https://realpython.com/lessons/duckdb-joining-data/#t=300.365
It takes an argument ashttps://realpython.com/lessons/duckdb-joining-data/#t=304.245
to which column in the results to perform the sorting upon.https://realpython.com/lessons/duckdb-joining-data/#t=305.505
05:07https://realpython.com/lessons/duckdb-joining-data/#t=307.785
The DESC keyword, pronounced descending,https://realpython.com/lessons/duckdb-joining-data/#t=307.785
means descending, specifying the sort order beinghttps://realpython.com/lessons/duckdb-joining-data/#t=312.105
that direction around. And there you go.https://realpython.com/lessons/duckdb-joining-data/#t=315.215
There were four presidents from the Whig party.https://realpython.com/lessons/duckdb-joining-data/#t=319.535
05:22https://realpython.com/lessons/duckdb-joining-data/#t=322.515
How funny is that? One of them’s named Millard.https://realpython.com/lessons/duckdb-joining-data/#t=322.515
I swear to you, I didn’t plan that. You may recallhttps://realpython.com/lessons/duckdb-joining-data/#t=325.375
I said it was good practicehttps://realpython.com/lessons/duckdb-joining-data/#t=329.305
to close your connection when you’re done with it.https://realpython.com/lessons/duckdb-joining-data/#t=330.425
05:32https://realpython.com/lessons/duckdb-joining-data/#t=332.635
This is me doing that. To come full circle,https://realpython.com/lessons/duckdb-joining-data/#t=332.635
let’s see the same idea using in-memory operations.https://realpython.com/lessons/duckdb-joining-data/#t=335.495
05:45https://realpython.com/lessons/duckdb-joining-data/#t=345.085
Note, I’m not using a connection here.https://realpython.com/lessons/duckdb-joining-data/#t=345.085
The same read methods are available directly on the module.https://realpython.com/lessons/duckdb-joining-data/#t=347.275
05:55https://realpython.com/lessons/duckdb-joining-data/#t=355.705
I’ve got both presidents and parties as relation objects.https://realpython.com/lessons/duckdb-joining-data/#t=355.705
Remember, these aren’t tables. The connection’s closed.https://realpython.com/lessons/duckdb-joining-data/#t=359.925
Python no longer knows about those tables at all.https://realpython.com/lessons/duckdb-joining-data/#t=362.945
06:06https://realpython.com/lessons/duckdb-joining-data/#t=366.405
Queries can be performed on relation objectshttps://realpython.com/lessons/duckdb-joining-data/#t=366.405
as if they were tableshttps://realpython.com/lessons/duckdb-joining-data/#t=368.305
by using the sql() function directly on the DuckDB module.https://realpython.com/lessons/duckdb-joining-data/#t=369.425
06:27https://realpython.com/lessons/duckdb-joining-data/#t=387.705
Same query, same results,https://realpython.com/lessons/duckdb-joining-data/#t=387.705
but this time it was done on the memory objectshttps://realpython.com/lessons/duckdb-joining-data/#t=390.735
instead. I’ve been fasthttps://realpython.com/lessons/duckdb-joining-data/#t=393.235
and loose with the names here, using presidentshttps://realpython.com/lessons/duckdb-joining-data/#t=395.255
to mean a table earlier and a relation now.https://realpython.com/lessons/duckdb-joining-data/#t=397.695
06:41https://realpython.com/lessons/duckdb-joining-data/#t=401.075
You can almost think of them as the same thingshttps://realpython.com/lessons/duckdb-joining-data/#t=401.075
as you can perform queries on either,https://realpython.com/lessons/duckdb-joining-data/#t=403.395
but make sure you don’t confuse them.https://realpython.com/lessons/duckdb-joining-data/#t=405.195
The relation only lives as long as this REPL session,https://realpython.com/lessons/duckdb-joining-data/#t=406.875
whereas the table can be accessed again by connectinghttps://realpython.com/lessons/duckdb-joining-data/#t=409.805
to the database once more.https://realpython.com/lessons/duckdb-joining-data/#t=412.535
06:55https://realpython.com/lessons/duckdb-joining-data/#t=415.385
Let’s do this one more time in a third way, this timehttps://realpython.com/lessons/duckdb-joining-data/#t=415.385
through method calls.https://realpython.com/lessons/duckdb-joining-data/#t=418.655
07:05https://realpython.com/lessons/duckdb-joining-data/#t=425.515
There’s a little bit of housekeeping necessaryhttps://realpython.com/lessons/duckdb-joining-data/#t=425.515
before using the API. You need to give DuckDB a namehttps://realpython.com/lessons/duckdb-joining-data/#t=427.365
to associate with your relation object for usehttps://realpython.com/lessons/duckdb-joining-data/#t=431.185
inside the API calls.https://realpython.com/lessons/duckdb-joining-data/#t=434.105
07:20https://realpython.com/lessons/duckdb-joining-data/#t=440.415
You can think of this likehttps://realpython.com/lessons/duckdb-joining-data/#t=440.415
registering the object with a name.https://realpython.com/lessons/duckdb-joining-data/#t=441.715
This name doesn’t have to be the same as the namehttps://realpython.com/lessons/duckdb-joining-data/#t=443.425
of the variable you’re using to store the relation object,https://realpython.com/lessons/duckdb-joining-data/#t=445.475
but typically that’s what you do.https://realpython.com/lessons/duckdb-joining-data/#t=448.215
07:30https://realpython.com/lessons/duckdb-joining-data/#t=450.515
Now, let me construct the same query as before,https://realpython.com/lessons/duckdb-joining-data/#t=450.515
but this time using chained method calls.https://realpython.com/lessons/duckdb-joining-data/#t=452.635
The reason for the aliases will be clearer in a second.https://realpython.com/lessons/duckdb-joining-data/#t=455.785
07:39https://realpython.com/lessons/duckdb-joining-data/#t=459.825
Starting with the president’s relation object,https://realpython.com/lessons/duckdb-joining-data/#t=459.825
07:48https://realpython.com/lessons/duckdb-joining-data/#t=468.045
and chaining a join() method.https://realpython.com/lessons/duckdb-joining-data/#t=468.045
This takes the party’s relationship object as an argumenthttps://realpython.com/lessons/duckdb-joining-data/#t=470.055
and a condition for the joining.https://realpython.com/lessons/duckdb-joining-data/#t=473.365
The condition is a string. Inside the string,https://realpython.com/lessons/duckdb-joining-data/#t=475.885
you need to reference the objects, hence the alias.https://realpython.com/lessons/duckdb-joining-data/#t=478.785
08:02https://realpython.com/lessons/duckdb-joining-data/#t=482.855
DuckDB parses the condition like it doeshttps://realpython.com/lessons/duckdb-joining-data/#t=482.855
inside an SQL statement,https://realpython.com/lessons/duckdb-joining-data/#t=485.085
and the alias is what tells ithttps://realpython.com/lessons/duckdb-joining-data/#t=486.805
to associate those names in the conditionhttps://realpython.com/lessons/duckdb-joining-data/#t=488.345
with the relation objects.https://realpython.com/lessons/duckdb-joining-data/#t=490.615
08:13https://realpython.com/lessons/duckdb-joining-data/#t=493.205
This is kind of messy.https://realpython.com/lessons/duckdb-joining-data/#t=493.205
If you’re used to ORMs like SQLAlchemy or Django,https://realpython.com/lessons/duckdb-joining-data/#t=494.875
this feels kind of fragile.https://realpython.com/lessons/duckdb-joining-data/#t=498.205
Both those ORMs have ways of writing this kind of expressionhttps://realpython.com/lessons/duckdb-joining-data/#t=500.565
with objects instead.https://realpython.com/lessons/duckdb-joining-data/#t=503.375
08:24https://realpython.com/lessons/duckdb-joining-data/#t=504.835
But hey, it works. With the tableshttps://realpython.com/lessons/duckdb-joining-data/#t=504.835
joined, the select() method specifies the names of the columnshttps://realpython.com/lessons/duckdb-joining-data/#t=508.675
for our result, and then the filter() callhttps://realpython.com/lessons/duckdb-joining-data/#t=511.715
enacts the WHERE clause.https://realpython.com/lessons/duckdb-joining-data/#t=515.545
08:37https://realpython.com/lessons/duckdb-joining-data/#t=517.955
Finally, a call to order()https://realpython.com/lessons/duckdb-joining-data/#t=517.955
to sort the results, and there you go.https://realpython.com/lessons/duckdb-joining-data/#t=519.625
Third way, same result.https://realpython.com/lessons/duckdb-joining-data/#t=523.225
The API method’s a little more verbose than writing SQLhttps://realpython.com/lessons/duckdb-joining-data/#t=525.405
queries directly, but from your IDE’s perspective,https://realpython.com/lessons/duckdb-joining-data/#t=528.305
SQL is just a string.https://realpython.com/lessons/duckdb-joining-data/#t=531.005
08:52https://realpython.com/lessons/duckdb-joining-data/#t=532.515
Using the API like this gives you type hintinghttps://realpython.com/lessons/duckdb-joining-data/#t=532.515
and compiler enforcement, making bugs a little lesshttps://realpython.com/lessons/duckdb-joining-data/#t=535.11
likely. When done right,https://realpython.com/lessons/duckdb-joining-data/#t=537.845
it also helps deal with SQL injection.https://realpython.com/lessons/duckdb-joining-data/#t=539.785
09:02https://realpython.com/lessons/duckdb-joining-data/#t=542.245
I won’t go into that here.https://realpython.com/lessons/duckdb-joining-data/#t=542.245
The short version is if a user is passing you stringshttps://realpython.com/lessons/duckdb-joining-data/#t=543.905
that you’re basing your query upon, they could include stuffhttps://realpython.com/lessons/duckdb-joining-data/#t=546.805
that mangles your SQL.https://realpython.com/lessons/duckdb-joining-data/#t=549.565
09:10https://realpython.com/lessons/duckdb-joining-data/#t=550.905
And when I say mangle,https://realpython.com/lessons/duckdb-joining-data/#t=550.905
I mean vicious things like deleting data or tables.https://realpython.com/lessons/duckdb-joining-data/#t=552.205
For a little more information on this, Google OWASP,https://realpython.com/lessons/duckdb-joining-data/#t=555.225
that’s O-W-A-S-P SQL injection attackshttps://realpython.com/lessons/duckdb-joining-data/#t=558.025
for a little bit of homework.https://realpython.com/lessons/duckdb-joining-data/#t=561.785
09:25https://realpython.com/lessons/duckdb-joining-data/#t=565.495
Why did the mallard want to be an accountant?https://realpython.com/lessons/duckdb-joining-data/#t=565.495
Because he loved deductions. Tip your waitress.https://realpython.com/lessons/duckdb-joining-data/#t=567.745
I’ll be here all week. Next up, howhttps://realpython.com/lessons/duckdb-joining-data/#t=571.795
to incorporate Python functions into your DuckDB queries.https://realpython.com/lessons/duckdb-joining-data/#t=574.435
Become a Memberhttps://realpython.com/account/join/
https://realpython.com/lessons/accessing-data-relation-objects/
Overviewhttps://realpython.com/courses/starting-duckdb-python/
https://realpython.com/lessons/python-functions-inside-duckdb-queries/
Starting With DuckDB and Python (Overview) 02:39 https://realpython.com/videos/starting-duckdb-python-overview/
Reviewing SQL 07:53 https://realpython.com/videos/duckdb-reviewing-sql/
An Introduction to DuckDB 07:13 https://realpython.com/videos/introduction-duckdb/
Using DuckDB With Databases 05:03 https://realpython.com/videos/duckdb-databases/
Ingesting CSV Files 04:43 https://realpython.com/lessons/ingesting-csv-files/
Accessing Data in Relation Objects 03:28 https://realpython.com/lessons/accessing-data-relation-objects/
Joining Data 09:39 https://realpython.com/lessons/duckdb-joining-data/
Using Python Functions Inside DuckDB Queries 05:25 https://realpython.com/lessons/python-functions-inside-duckdb-queries/
Starting With DuckDB and Python (Quiz) 06:30 https://realpython.com/lessons/starting-duckdb-python-quiz/
Starting With DuckDB and Python (Summary) 02:33 https://realpython.com/lessons/starting-duckdb-python-summary/
Privacy Policyhttps://realpython.com/privacy-policy/

Viewport: width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover

Robots: max-image-preview:large


URLs of crawlers that visited me.