Pandas & NumPy Academy · Les

SQL-query's uitvoeren vanuit Pandas

Voer willekeurige SELECT-instructies uit met pd.read_sql_query en parameteriseer query's veilig om SQL-injectie te voorkomen.

Les 2 van 413 stappen

SQL-query's uitvoeren vanuit Pandas is een gratis Pandas & NumPy Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Pandas & NumPy Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

pd.read_sql: de uniforme interface

Pandas biedt drie SQL-leesfuncties: pd.read_sql() (algemene wrapper), pd.read_sql_table() (leest een volledige tabel op naam) en pd.read_sql_query() (voert willekeurige SQL uit). Voor de meeste analytische workflows is pd.read_sql_query() het krachtigst, omdat je hiermee elke SELECT-instructie kunt schrijven en gegevens kunt filteren, joinen en aggregeren voordat ze Pandas bereiken. SQL gebruiken voor het zware werk en Pandas voor de uiteindelijke analyse is vaak efficiënter dan alles laden en in Python filteren.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///ecommerce.db')

# Three equivalent patterns
df1 = pd.read_sql('SELECT * FROM orders LIMIT 100', con=engine)
df2 = pd.read_sql_table('orders', con=engine)  # full table
df3 = pd.read_sql_query('SELECT * FROM orders LIMIT 100', con=engine)

print(df3.head())
print(df3.columns.tolist())

Filteren op databaseniveau

Filter gegevens altijd in SQL in plaats van alles te laden en in Pandas te filteren. Een database met goede indexen kan een WHERE-clausule op miljoenen rijen uitvoeren en binnen milliseconden slechts duizenden rijen teruggeven, terwijl Pandas eerst gigabytes aan gegevens zou moeten laden. De gouden regel: predicaten naar de database verplaatsen. Gebruik WHERE voor rijfilters, SELECT col1, col2 voor kolomselectie en LIMIT tijdens de ontwikkeling om snel een voorbeeld van de resultaten te bekijken.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Filter and project at SQL level — only fetch what you need
query = '''
    SELECT order_id, customer_id, amount, status
    FROM orders
    WHERE status = 'completed'
      AND order_date >= '2024-01-01'
      AND amount > 50
    LIMIT 1000
'''

df = pd.read_sql_query(query, con=engine)
print(f'Rows: {len(df)}, Columns: {list(df.columns)}')

Ageren in SQL versus Pandas

Voor eenvoudige samenvattingen per groep over grote tabellen zijn SQL-aggregaties sneller dan Pandas, omdat de database-engine indexen, parallelle uitvoering en aggregatie met hashing op schijf kan gebruiken. Gebruik SQL voor GROUP BY en SUM/COUNT/AVG wanneer de tabel groot is. Laad het geaggregeerde resultaat (een kleine DataFrame) in Pandas voor verdere analyse, visualisatie of combinatie met andere gegevens. Voor complexe aangepaste aggregaties die SQL niet kan uitdrukken, laad je een gefilterde subset in Pandas en gebruik je daar groupby.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Aggregate in SQL — returns a small result set
query = '''
    SELECT region,
           COUNT(*) AS order_count,
           ROUND(SUM(amount), 2) AS total_revenue,
           ROUND(AVG(amount), 2) AS avg_order_value
    FROM orders
    WHERE status = 'completed'
    GROUP BY region
    ORDER BY total_revenue DESC
'''

df = pd.read_sql_query(query, con=engine)
print(df)

JOIN's in SQL-query's

SQL-JOIN-bewerkingen zijn efficiënter dan Pandas merge() voor joins op grote tabellen, omdat de database geïndexeerde zoekopdrachten kan gebruiken. Schrijf je join in SQL en ontvang in Pandas een vooraf gejoind, eventueel gefilterd resultaat. Voor analyses met meerdere tabellen is één SQL-query met meerdere JOIN's doorgaans sneller dan elke tabel afzonderlijk lezen en in Pandas samenvoegen, vooral wanneer een tabel miljoenen rijen bevat en de join het resultaat aanzienlijk verkleint.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///ecommerce.db')

query = '''
    SELECT o.order_id,
           c.customer_name,
           c.country,
           p.product_name,
           o.amount
    FROM orders o
    JOIN customers c ON o.customer_id = c.id
    JOIN products p ON o.product_id = p.id
    WHERE o.status = 'completed'
    LIMIT 500
'''

df = pd.read_sql_query(query, con=engine)
print(df.head())

Python-variabelen in query's gebruiken

Gebruik SQLAlchemy's text() met benoemde parameters om Python-variabelen veilig in SQL-query's te gebruiken. Definieer plaatshouders met :param_name in de querytekenreeks en geef een woordenboek door aan het argument params van read_sql_query. Dit werkt zowel voor afzonderlijke waarden als — met sommige databases — voor lijsten. Gebruik geen f-tekenreeksen of %-opmaak om querytekenreeksen uit variabelen op te bouwen; dit is onveilig, zelfs voor intern gebruik.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Python variables to inject
min_amount = 200.0
start_date = '2024-01-01'
end_date = '2024-12-31'

query = sa.text('''
    SELECT * FROM orders
    WHERE amount > :min_amount
      AND order_date BETWEEN :start_date AND :end_date
''')

with engine.connect() as conn:
    df = pd.read_sql_query(query, con=conn,
                           params={'min_amount': min_amount,
                                   'start_date': start_date,
                                   'end_date': end_date})
print(f'{len(df)} orders found')

CTE's en subquery's gebruiken

Voor complexe analyses zijn vaak Common Table Expressions (CTE's) of subquery's nodig. Deze worden volledig ondersteund door pd.read_sql_query — geef gewoon de volledige SQL met meerdere clausules door als querytekenreeks. CTE's (geïntroduceerd met het sleutelwoord WITH) maken complexe query's leesbaarder door tussenresultaten een naam te geven. Dit is handig voor berekeningen van lopende totalen, rangschikkingen binnen groepen en filtering in meerdere stappen die in Pandas veel omslachtiger zou zijn.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

query = '''
    WITH monthly_revenue AS (
        SELECT strftime('%Y-%m', order_date) AS month,
               SUM(amount) AS revenue
        FROM orders
        WHERE status = 'completed'
        GROUP BY month
    )
    SELECT month,
           revenue,
           revenue - LAG(revenue) OVER (ORDER BY month)
               AS month_over_month_change
    FROM monthly_revenue
    ORDER BY month
'''

df = pd.read_sql_query(query, con=engine)
print(df.tail())

Lezen met een DatetimeIndex

Stel bij het lezen van tijdreeksgegevens uit een database de kolom met tijdstempels in als index van de DataFrame door index_col='date_column' en parse_dates=['date_column'] door te geven aan read_sql_query. Zo krijg je rechtstreeks een DatetimeIndex, waarmee je tijdgebaseerde selecties in Pandas (df['2024-01']), her bemonstering en voortschrijdende berekeningen kunt uitvoeren zonder extra nabewerking. Het argument parse_dates vertelt Pandas de kolom om te zetten naar datetime64.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///metrics.db')

df = pd.read_sql_query(
    'SELECT recorded_at, metric_value FROM daily_metrics ORDER BY recorded_at',
    con=engine,
    index_col='recorded_at',
    parse_dates=['recorded_at']
)
print(df.index.dtype)   # datetime64[ns]
print(df['2024-06'])    # Slice by month directly

Trage query's profileren

Wanneer een query traag is, voeg je het SQL-trefwoord EXPLAIN toe (of EXPLAIN QUERY PLAN in SQLite) vóór je SELECT om het uitvoeringsplan van de database te bekijken. Let op volledige tabelscans ('SCAN TABLE') op plaatsen waar je indexzoekacties ('SEARCH TABLE') zou verwachten. Ontbrekende indexen op WHERE- en JOIN-kolommen zijn de meest voorkomende oorzaak van trage query's. Maak de juiste index aan in de database en controleer opnieuw met EXPLAIN voordat je de Pandas-pijplijn opnieuw uitvoert.

import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Check if the query uses an index
with engine.connect() as conn:
    plan = conn.execute(sa.text(
        'EXPLAIN QUERY PLAN SELECT * FROM orders WHERE customer_id = 42'
    )).fetchall()
    for row in plan:
        print(row)
    # Look for 'SEARCH TABLE orders USING INDEX' — not 'SCAN TABLE'

Paginering voor grote resultaatsets

Wanneer je interactief door een grote resultaatset loopt (bijvoorbeeld door telkens één pagina met resultaten te verwerken), gebruik je SQL LIMIT en OFFSET om paginering te implementeren. Haal telkens N rijen op, verwerk ze en haal daarna de volgende N op. Hoewel dit minder efficiënt is dan de chunksize-aanpak (die een cursor bijhoudt), is paginering nuttig wanneer rijen stapsgewijs in een rapport moeten worden weergegeven of wanneer je resultaten uit meerdere query's combineert.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')
page_size = 10000
offset = 0

while True:
    query = sa.text(
        'SELECT * FROM orders ORDER BY order_id LIMIT :limit OFFSET :offset'
    )
    with engine.connect() as conn:
        df = pd.read_sql_query(query, con=conn,
                               params={'limit': page_size, 'offset': offset})
    if len(df) == 0:
        break
    print(f'Page at offset {offset}: {len(df)} rows')
    offset += page_size

SQL-query's combineren met Pandas-logica

Het krachtigste patroon is een hybride pijplijn: gebruik SQL voor filtering en aggregatie op hoofdlijnen en gebruik daarna Pandas voor verfijnde transformaties die in SQL omslachtig zijn (draaitabellen, tekenreeksparsing, apply-functies en voortschrijdende vensters). Lees een beheersbare resultaatset uit SQL (duizenden rijen) en koppel vervolgens Pandas-bewerkingen aan het resulterende DataFrame. Zo combineer je de sterke punten van beide hulpmiddelen en blijven de gegevens door één Python-proces stromen.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# SQL: coarse filter and join
df = pd.read_sql_query('''
    SELECT o.customer_id, o.amount, o.order_date, c.country
    FROM orders o JOIN customers c ON o.customer_id = c.id
    WHERE o.status = 'completed'
''', con=engine, parse_dates=['order_date'])

# Pandas: rolling 30-day revenue per country
df = df.sort_values('order_date')
df['rolling_30d'] = (
    df.groupby('country')['amount']
    .transform(lambda x: x.rolling('30D').sum())
)
print(df.head())

Foutafhandeling voor databasequery's

Databasequery's kunnen mislukken door netwerk-time-outs, syntaxisfouten of verbroken verbindingen. Plaats databaseaanroepen in try-except-blokken die sqlalchemy.exc.OperationalError opvangen voor verbindingsproblemen en sqlalchemy.exc.ProgrammingError voor SQL-syntaxisfouten. Registreer de fout met context (query, parameters) en probeer het opnieuw met exponentiële wachttijden, of handel de fout netjes af. In productie-pijplijnen is het essentieel om tijdelijke fouten (opnieuw proberen) te onderscheiden van permanente fouten (de SQL corrigeren).

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

try:
    df = pd.read_sql_query(
        'SELECT * FROM nonexistent_table',
        con=engine
    )
except sa.exc.OperationalError as e:
    print(f'Connection or table error: {e}')
except sa.exc.ProgrammingError as e:
    print(f'SQL syntax error: {e}')
except Exception as e:
    print(f'Unexpected error: {type(e).__name__}: {e}')

Korte controle

Toets je begrip van de concepten voor gegevensanalyse uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat pd.read_sql_query() elke SQL SELECT uitvoert en een DataFrame retourneert, dat filters en aggregaties naar SQL verplaatsen efficiënter is dan volledige tabellen in Pandas laden en dat hybride pijplijnen SQL gebruiken voor gegevensreductie op hoofdlijnen en Pandas voor verfijnde, aangepaste transformaties. Hierna leer je hoe je DataFrames terugschrijft naar databasetabellen.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “SQL-query's uitvoeren vanuit Pandas” gratis?

Ja — de volledige tekst van “SQL-query's uitvoeren vanuit Pandas” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Pandas & NumPy Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Wat leer ik in “SQL-query's uitvoeren vanuit Pandas”?

Voer willekeurige SELECT-instructies uit met pd.read_sql_query en parameteriseer query's veilig om SQL-injectie te voorkomen. Je oefent met Pandas & NumPy Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Pandas & NumPy Academy te beginnen?

Ervaring vooraf is niet nodig. Pandas & NumPy Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.

Hoe lang duurt de les “SQL-query's uitvoeren vanuit Pandas”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Pandas & NumPy Academy?

Ja. Elke les over Pandas & NumPy Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Verbinden met een database met SQLAlchemy
  2. SQL-query's uitvoeren vanuit Pandas
  3. DataFrames naar databasetabellen schrijven
  4. Pandas versus SQL: het juiste hulpmiddel kiezen
← Terug naar Pandas & NumPy Academy