Pandas & NumPy Academy · Lektion

Kör SQL-frågor från Pandas

Kör godtyckliga SELECT-satser med pd.read_sql_query och parameterisera frågor säkert för att undvika SQL-injektion.

Lektion 2 av 413 steg

Kör SQL-frågor från Pandas är en gratis lektion i Pandas & NumPy Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Pandas & NumPy Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Pandas & NumPy Academy innehåller totalt 4 lektioner.

pd.read_sql: det enhetliga gränssnittet

Pandas har tre funktioner för att läsa SQL: pd.read_sql() (generellt omslag), pd.read_sql_table() (läser en hel tabell utifrån namn) och pd.read_sql_query() (kör godtycklig SQL). För de flesta analytiska arbetsflöden är pd.read_sql_query() kraftfullast, eftersom ni kan skriva valfri SELECT-sats med filtrering, join-operationer och aggregering innan data når Pandas. Att använda SQL för de tunga operationerna och Pandas för den slutliga analysen är ofta effektivare än att läsa in allt och filtrera i Python.

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())

Filtrera på databasnivå

Filtrera alltid data i SQL i stället för att läsa in allt och filtrera i Pandas. En databas med korrekta index kan köra en WHERE-sats på miljontals rader och returnera bara några tusen på millisekunder, medan Pandas först måste läsa in gigabyte med data. Grundregeln är: skicka predikat till databasen. Använd WHERE för radfilter, SELECT col1, col2 för kolumnurval och LIMIT under utvecklingen för att snabbt förhandsgranska resultat.

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)}')

Aggregering i SQL jämfört med Pandas

För enkla sammanfattningar per grupp över stora tabeller är SQL-aggregeringar effektivare än Pandas, eftersom databasmotorn kan använda index, parallell körning och hashaggregering på disk. Använd SQL för GROUP BY och SUM/COUNT/AVG när tabellen är stor. Läs in det aggregerade resultatet (en liten DataFrame) i Pandas för vidare analys, visualisering eller kombination med andra data. För komplexa anpassade aggregeringar som SQL inte kan uttrycka läser ni in ett filtrerat delmängd i Pandas och använder groupby där.

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-operationer i SQL-frågor

SQL:s JOIN-operationer är effektivare än Pandas merge() för join-operationer på stora tabeller, eftersom databasen kan använda indexerade uppslag. Skriv join-operationen i SQL och ta emot ett redan sammanfogat, eventuellt filtrerat resultat i Pandas. Vid analys av flera tabeller är en enda SQL-fråga med flera JOIN-operationer vanligtvis snabbare än att läsa varje tabell separat och sammanfoga dem i Pandas, särskilt när en tabell har miljontals rader och join-operationen minskar resultatet avsevärt.

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())

Använda Python-variabler i frågor

För att på ett säkert sätt infoga Python-variabler i SQL-frågor använder ni SQLAlchemys text() med namngivna parametrar. Definiera platshållare med :param_name i frågesträngen och skicka en ordlista till argumentet params i read_sql_query. Detta fungerar både för enskilda värden och — med vissa databaser — för listor. Undvik f-strängar eller %-formatering för att bygga frågesträngar från variabler; de är osäkra även vid intern användning.

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')

Använda CTE:er och underfrågor

Komplexa analyser kräver ofta Common Table Expressions (CTE:er) eller underfrågor. Dessa stöds fullt ut av pd.read_sql_query — skicka bara hela SQL-frågan med flera satser som frågesträngen. CTE:er (som inleds med nyckelordet WITH) gör komplexa frågor mer läsbara genom att namnge mellanresultat. Detta är användbart för beräkningar av löpande summor, rangordning inom grupper och filtrering i flera steg som skulle bli omständlig i Pandas.

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())

Läsa in med ett DatetimeIndex

När ni läser tidsseriedata från en databas anger ni tidsstämpelkolumnen som DataFrame-index genom att skicka index_col='date_column' och parse_dates=['date_column'] till read_sql_query. Då får ni ett DatetimeIndex direkt, vilket möjliggör tidsbaserad uppdelning i Pandas (df['2024-01']), omsampling och rullande beräkningar utan extra efterbehandling. Argumentet parse_dates instruerar Pandas att konvertera kolumnen till 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

Profilera långsamma frågor

När en fråga går långsamt kan du lägga till SQL-nyckelordet EXPLAIN (eller EXPLAIN QUERY PLAN i SQLite) före din SELECT-sats för att se databasens körplan. Leta efter fullständiga tabellskanningar ('SCAN TABLE') där du förväntar dig indexuppslag ('SEARCH TABLE'). Saknade index på WHERE- och JOIN-kolumner är den vanligaste orsaken till långsamma frågor. Skapa det lämpliga indexet i databasen och kontrollera igen med EXPLAIN innan du kör om Pandas-pipelinen.

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'

Sidindelning för stora resultatmängder

När du interaktivt itererar över en stor resultatmängd (till exempel när du bearbetar en resultatsida i taget) använder du SQL LIMIT och OFFSET för att implementera sidindelning. Hämta N rader åt gången, bearbeta dem och hämta sedan nästa N rader. Även om detta är mindre effektivt än metoden med chunksize (som behåller en cursor) är sidindelning användbar när rader måste visas stegvis i en rapport eller när resultat från flera frågor kombineras.

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

Kombinera SQL-frågor med Pandas-logik

Det mest kraftfulla mönstret är en hybridpipeline: använd SQL för grov filtrering och aggregering och Pandas för finare transformationer som SQL uttrycker på ett omständligt sätt (pivottabeller, strängtolkning, apply-funktioner och rullande fönster). Läs in en hanterbar resultatmängd från SQL (tusentals rader) och kedja sedan Pandas-operationer på den resulterande DataFrame. På så sätt kombineras styrkorna hos båda verktygen samtidigt som dataflödet hålls inom en enda Python-process.

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())

Felhantering för databasfrågor

Databasfrågor kan misslyckas på grund av nätverkstimeouter, syntaxfel eller förlorade anslutningar. Omge databasanrop med try-except-block som fångar sqlalchemy.exc.OperationalError för anslutningsproblem och sqlalchemy.exc.ProgrammingError för SQL-syntaxfel. Logga felet tillsammans med sammanhang (fråga och parametrar) och försök antingen igen med exponentiell backoff eller avsluta på ett kontrollerat sätt. I produktionspipelines är det viktigt att skilja tillfälliga fel (som kan hanteras genom nya försök) från permanenta fel (där SQL-koden måste rättas).

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}')

Snabbtest

Testa din förståelse av dataanalysbegreppen från den här lektionen.

Sammanfattning av lektionen

I den här lektionen har du lärt dig att pd.read_sql_query() kör valfri SQL SELECT och returnerar en DataFrame, att skicka filter och aggregeringar till SQL är effektivare än att läsa in hela tabeller i Pandas och att hybridpipelines kombinerar SQL för grov datareduktion med Pandas för finare anpassade transformationer. Nästa steg är att lära dig skriva tillbaka DataFrames till databastabeller.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Kör SQL-frågor från Pandas” gratis?

Ja – hela texten till ”Kör SQL-frågor från Pandas” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Pandas & NumPy Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Pandas & NumPy Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Kör SQL-frågor från Pandas”?

Kör godtyckliga SELECT-satser med pd.read_sql_query och parameterisera frågor säkert för att undvika SQL-injektion. Ni övar på Pandas & NumPy Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Pandas & NumPy Academy?

Du behöver inga förkunskaper. Utbildningen i Pandas & NumPy Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”Kör SQL-frågor från Pandas”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Pandas & NumPy Academy-lektionen?

Ja. Varje Pandas & NumPy Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Anslut till en databas med SQLAlchemy
  2. Kör SQL-frågor från Pandas
  3. Skriv DataFrames till databastabeller
  4. Pandas kontra SQL: välj rätt verktyg
← Tillbaka till Pandas & NumPy Academy