Du ska inte behöva göra en miniutredning varje gång någon frågar: ”Kan du plocka fram siffrorna för det här?” Men det är precis vad som händer när svaret finns i Postgres och förfrågan kommer som luddig, vanlig svenska.
Marketing Ops märker det när kampanjrapportering blir en SQL-kö. En verksamhetsansvarig märker det när den ”snabba frågan” blir två dagar av fram-och-tillbaka. Och datadrivna analytiker hamnar som barnvakter för förfrågningar i stället för att analysera. Den här Postgres Sheets-automationen gör om frågor i naturligt språk till Postgres-resultat som du snabbt kan föra över till Google Sheets.
Du får se hur arbetsflödet genererar SQL på ett säkert sätt, kör den, formaterar utdata och returnerar något som teamet kan lita på och dela.
Så fungerar den här automationen
Se hur detta löser problemet:
n8n Workflow Template: Postgres + Google Sheets: svar utan SQL-krångel
flowchart LR
subgraph sg0["Chat Flow"]
direction LR
n0@{ icon: "mdi:swap-vertical", form: "rounded", label: "Add table name to output", pos: "b", h: 48 }
n1@{ icon: "mdi:cog", form: "rounded", label: "Convert data to binary", pos: "b", h: 48 }
n2@{ icon: "mdi:cog", form: "rounded", label: "Save file locally", pos: "b", h: 48 }
n3@{ icon: "mdi:cog", form: "rounded", label: "Extract data from file", pos: "b", h: 48 }
n4@{ icon: "mdi:play-circle", form: "rounded", label: "Chat Trigger", pos: "b", h: 48 }
n5@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking 'Test workflow'", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-vertical", form: "rounded", label: "Combine schema data and chat..", pos: "b", h: 48 }
n7@{ icon: "mdi:cog", form: "rounded", label: "Load the schema from the loc..", pos: "b", h: 48 }
n8@{ icon: "mdi:swap-vertical", form: "rounded", label: "Extract SQL query", pos: "b", h: 48 }
n9@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check if query exists", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Format query results", pos: "b", h: 48 }
n11["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Combine query result and cha.."]
n12["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>List all columns in a table"]
n13["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>List all tables in a database"]
n14@{ icon: "mdi:brain", form: "rounded", label: "Ollama Chat Model", pos: "b", h: 48 }
n15["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Postgres"]
n16@{ icon: "mdi:swap-vertical", form: "rounded", label: "Add trailing semicolon", pos: "b", h: 48 }
n17@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check for trailing semicolon", pos: "b", h: 48 }
n18@{ icon: "mdi:play-circle", form: "rounded", label: "WorkflowTrigger", pos: "b", h: 48 }
n19@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If ran manually", pos: "b", h: 48 }
n20@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If file exists or already re..", pos: "b", h: 48 }
n21@{ icon: "mdi:robot", form: "rounded", label: "AI Agent", pos: "b", h: 48 }
n22@{ icon: "mdi:swap-vertical", form: "rounded", label: "Format empty output", pos: "b", h: 48 }
n21 --> n8
n15 --> n10
n4 --> n7
n19 --> n7
n18 --> n7
n8 --> n17
n14 -.-> n21
n2 --> n19
n10 --> n11
n9 --> n11
n9 --> n15
n9 --> n22
n16 --> n9
n1 --> n2
n3 --> n6
n0 --> n1
n12 --> n0
n17 --> n16
n17 --> n9
n13 --> n12
n5 --> n13
n6 --> n21
n7 --> n20
n20 --> n3
n20 --> n13
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n4,n5,n18 trigger
class n21 ai
class n14 aiModel
class n9,n17,n19,n20 decision
class n12,n13,n15 database
classDef customIcon fill:none,stroke:none
class n11,n12,n13,n15 customIcon
Utmaningen: få svar från Postgres utan SQL-pingpong
De flesta ”enkla” rapportförfrågningar är egentligen inte enkla. Någon ber om ”registreringar per källa förra månaden”, men definitionerna är otydliga, tabellnamnen är okända och datan behöver en snabb upprensning innan den går att dela. Så du ställer följdfrågor, skriver en query, klistrar in resultat i ett kalkylark, inser att ett filter var fel och gör om. Under tiden väntar den som frågade, förtroendet sjunker och du börjar se flera kopior av ”final_report_v7” flyta runt.
Friktionen blir snabbt större. Här är var det brukar fallera i riktiga team.
- En ”snabb pull” från Postgres blir en timme eftersom schemat bara finns i någons huvud (eller i en gammal dokumentation).
- Att kopiera och klistra query-resultat till Google Sheets bjuder in små misstag som är svåra att upptäcka senare.
- Folk börjar undvika databasen helt, så beslut tas på gamla exporter och magkänsla.
- Analytiker blir en flaskhals, vilket gör att viktiga frågor ställs mer sällan.
Lösningen: frågor i naturligt språk som ger Postgres-färdiga resultat
Det här arbetsflödet tar emot en fråga i vanlig svenska, använder en AI-agent för att generera SQL och kör sedan den SQL:en mot din Postgres-databas för att returnera strukturerade resultat. Första gången du kör det läser det automatiskt in dina databastabeller och kolumner och sparar sedan schemat lokalt så att AI:n inte gissar tabellnamn. När en fråga sedan kommer in (från en chattrigger i n8n eller som en sub-workflow-trigger) laddar arbetsflödet schemat, blandar in det i AI-prompten och ber modellen skriva en query som matchar din förfrågan. Till sist kontrollerar det att queryn finns, säkerställer att SQL:en avslutas korrekt, kör den och formaterar utdata till ett svar som är enkelt att lägga in i Google Sheets.
Arbetsflödet börjar med en fråga och en sparad schema-snapshot. Därefter genererar AI:n SQL förankrad i din faktiska tabellstruktur. Postgres kör den, och du får ett svar som innehåller både SQL:en och resultaten.
Vad som förändras: före vs. efter
| Det här tar bort | Effekten du märker |
|---|---|
|
|
Praktisk effekt i verkligheten
Säg att du svarar på 10 datafrågor i veckan som landar i ett Google Sheet. Manuellt blir det ofta cirka 10 minuter för att reda ut frågan, cirka 20 minuter för att skriva och validera SQL och ytterligare 10 minuter för att formatera och klistra in i Sheets. Det är ungefär 40 minuter per fråga, eller runt 7 timmar i veckan. Med det här arbetsflödet skickar du in frågan en gång och får tillbaka SQL plus resultat på några minuter, så du hamnar närmare 1 timme av uppföljning i stället för en hel eftermiddag.
Krav
- n8n-instans (testa n8n Cloud gratis)
- Alternativ för self-hosting om du föredrar det (Hostinger fungerar bra)
- Postgres som databasen du vill fråga mot
- Google Sheets för att dela resultat i ett välkänt format
- LLM-åtkomst (Ollama lokalt, eller kompatibla inloggningsuppgifter för chattmodell)
Kunskapsnivå: Medel. Du bör vara bekväm med att koppla in credentials och bekräfta vilka databastabeller som är säkra att fråga mot.
Behöver du hjälp att implementera detta? Prata med en automationsexpert (gratis 15-minuters konsultation).
Arbetsflödets gång
En fråga triggar körningen. Du kan starta det från n8n:s chattrigger, köra det manuellt eller anropa det som ett sub-workflow från en annan automation som redan fångat upp frågan.
Arbetsflödet laddar ditt databasschema. Vid första körningen hämtar det tabell- och kolumndetaljer från Postgres och skriver en schemafil lokalt. Vid senare körningar läser det den filen så att AI:n får verklig kontext och färre chanser att hallucinerar fältnamn.
En AI-agent skriver SQL utifrån förfrågan. Prompten slår ihop användarens fråga med det sparade schemat, och språkmodellen (ofta Ollama lokalt) genererar ett SQL-uttryck som ska besvara frågan.
Postgres kör och utdata paketeras. Arbetsflödet kontrollerar att queryn finns, rättar små formateringsmissar, kör den i Postgres och formaterar sedan resultaten till ett svar som kan skickas vidare till ett Google Sheets-steg (eller ett annat arbetsflöde) utan extra efterarbete.
Du kan enkelt justera vilka tabeller som är synliga för AI:n för att stärka integritet och minska brus. Se hela implementationsguiden nedan för anpassningsalternativ.
Steg-för-steg-guide för implementering
Steg 1: konfigurera den manuella triggern
Det här arbetsflödet kan startas manuellt för att bygga eller uppdatera den lokala schemafilen som används av AI-frågegeneratorn.
- Lägg till noden Manual Run Trigger för att starta flödet för schemaimport.
- Koppla Manual Run Trigger till Retrieve Table List enligt körflödet.
- Låt inställningarna för Manual Run Trigger vara standard (inga parametrar krävs).
Steg 2: anslut PostgreSQL och bygg schemafilen
Det här steget hämtar tabellnamn och kolumner, etiketterar dem, serialiserar datan och skriver den till en lokal JSON-fil för senare användning.
- Öppna Retrieve Table List och ställ in Query till
SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='public'. - Inloggningsuppgifter krävs: anslut era PostgreSQL-inloggningsuppgifter i Retrieve Table List.
- I Retrieve Table Columns ställer ni in Query till
SELECT column_name, udt_name as data_type, CASE WHEN data_type = 'ARRAY' THEN TRUE ELSE FALSE END AS is_array, is_nullable FROM INFORMATION_SCHEMA.COLUMNS where table_name = '{{ $json.table_name }}'. - Inloggningsuppgifter krävs: anslut era PostgreSQL-inloggningsuppgifter i Retrieve Table Columns.
- I Append Table Label säkerställer ni att tilldelningen för table är
={{ $('Retrieve Table List').item.json.table_name ?? 'emails_metadata'}}och låter Include Other Fields vara aktiverat. - I Serialize Data File ställer ni in Operation till
toJson. - I Write File Local ställer ni in File Name till
=/files/pgsql-{{ $workflow.id }}.jsonoch Operation tillwrite. - Bekräfta att Write File Local går vidare till Manual Run Check för att villkora efterföljande flöden.
Steg 3: konfigurera chat- och subworkflow-indata
Det här arbetsflödet kan styras av en chattprompt eller en subworkflow-indata. Båda vägarna läser den lokala schemafilen innan AI:n promptas.
- Lämna Chat Input Trigger som den är för att ta emot chattindata i arbetsflödet.
- Lämna Subworkflow Input Trigger som den är med Workflow Inputs satt till
natural_language_query. - Säkerställ att både Chat Input Trigger och Subworkflow Input Trigger är kopplade till Read Local Schema.
- I Read Local Schema ställer ni in File Selector till
=/files/pgsql-{{ $workflow.id }}.json. - Bekräfta att Schema File Check utvärderar
{{ $input.item.binary }}och{{ $('Manual Run Check').isExecuted }}innan Parse File Data. - I Parse File Data ställer ni in Operation till
fromJson.
/files/pgsql-{{ $workflow.id }}.json.
Steg 4: sätt upp AI-generering av SQL
Det här steget slår ihop schemat och användarens prompt och använder sedan AI-agenten för att generera en SQL-fråga.
- I Merge Schema with Prompt säkerställer ni att följande fält tilldelas: sessionId till
={{ $('Chat Input Trigger').isExecuted && $('Chat Input Trigger').first().json.sessionId }}, action till={{ $('Chat Input Trigger').isExecuted && $('Chat Input Trigger').first().json.action }}, chatinput till={{ $('Subworkflow Input Trigger').isExecuted ? $('Subworkflow Input Trigger').first().json.natural_language_query: $('Chat Input Trigger').first().json.chatInput }}, och schema till={{ $json.data }}. - I SQL Generation Agent behåller ni prompten Text exakt som den är definierad, inklusive schemablocket och reglerna.
- Säkerställ att Ollama Language Model är ansluten som språkmodell för SQL Generation Agent.
- Ställ in Ollama Language Model Model till
phi4-mini:latest.
Steg 5: validera SQL och kör frågan
Arbetsflödet extraherar SQL-satsen, säkerställer att den slutar med semikolon, validerar den och kör den mot PostgreSQL.
- I Pull SQL Statement ställer ni in query till
={{ ($json.output.match(/SELECT[^;]*/i) || [])[0] || "" }}. - I Verify Semicolon End bekräftar ni att villkoren kontrollerar att
{{ $json.query }}inte är tomt och inte slutar med;. - I Append Semicolon ställer ni in query till
={{ $json.query }};. - I Validate Query Presence säkerställer ni att villkoret kontrollerar att
{{ $json.query }}inte är tomt. - Validate Query Presence skickar utdata parallellt till både Merge Results and Reply och Postgres Query Runner. Behåll det parallella flödet för att möjliggöra hantering av tomma frågor.
- I Postgres Query Runner ställer ni in Query till
{{ $json.query }}. - Inloggningsuppgifter krävs: anslut era PostgreSQL-inloggningsuppgifter i Postgres Query Runner.
Steg 6: formatera och slå ihop utdata
Frågeresultaten formateras till en läsbar sträng och slås sedan ihop med chattens svarflöde.
- I Format Query Output ställer ni in sqloutput till
={{ Object.keys($jmespath($input.all(),'[].json')[0]).join(' | ') }} {{ ($jmespath($input.all(),'[].json')).map(obj => Object.values(obj).join(' | ')).join('\n') }}. - Verifiera att Format Query Output är kopplad till Merge Results and Reply.
- I Merge Results and Reply låter ni Mode vara satt till
combineoch Combine By tillcombineByPosition.
sqloutput på ett robust sätt.
Steg 7: testa och aktivera ert arbetsflöde
Kör ett manuellt test och verifiera flödet för SQL-generering och exekvering innan ni aktiverar.
- Klicka på Execute Workflow för att köra Manual Run Trigger och skapa schemafilen.
- Trigga Chat Input Trigger med en testprompt (till exempel: ”senaste mejlen om budgetar”).
- Bekräfta att SQL Generation Agent matar ut en giltig SQL-sats och att Postgres Query Runner returnerar resultat.
- Verifiera att Merge Results and Reply tar emot både frågeresultaten och valideringsutdata.
- När ni är nöjda växlar ni arbetsflödet från Inactive till Active för att aktivera användning i produktion.
Saker att se upp med
- Postgres-credentials kan gå ut eller peka mot fel databas. Om resultaten plötsligt ser ”tomma” ut, kontrollera först n8n:s Postgres-credential och databasnamnet.
- Om du använder Wait-noder eller extern rendering varierar bearbetningstiderna. Öka väntetiden om nedströms noder fallerar på tomma svar.
- Standardprompter i AI-noder är generiska. Lägg in er tonalitet tidigt annars kommer du redigera utdata för alltid.
Vanliga frågor
Oftast cirka 30 minuter om Postgres-åtkomsten redan är på plats.
Ja, men någon behöver fortfarande sätta upp Postgres-anslutningen och bestämma vilka tabeller som är tillåtna. Därefter är det mest att användare ställer frågor och kopierar resultat till Sheets.
Ja. n8n har ett gratis self-hosted-alternativ och en gratis provperiod på n8n Cloud. Molnplaner börjar på 20 USD/månad för högre volymer. Du behöver också räkna in modellkostnader (Ollama lokalt är vanligtvis ”gratis” förutom beräkning, medan hostade LLM-API:er tar betalt per användning).
Två alternativ: n8n Cloud (hanterat, enklast att komma igång) eller self-hosting på en VPS. För self-hosting är Hostinger VPS prisvärd och klarar n8n bra. Self-hosting ger obegränsat antal körningar men kräver grundläggande serverhantering.
Du kan begränsa schemat som AI:n ser genom att filtrera steget ”Retrieve Table List” så att det bara inkluderar tabellerna du vill ha (till exempel en enda rapporttabell). Om du vill ha annan utdataformatering för Google Sheets justerar du mappningen i ”Format Query Output” så att den returnerar kolumnrubriker och rader på det sätt ditt team förväntar sig. Vanliga justeringar är att tvinga datumintervall, lägga till standardfilter (som att exkludera testkonton) och byta namn på fält så att de matchar affärsvänliga etiketter.
För det mesta är det credentialen, inte queryn. Kontrollera Postgres-credentialen i n8n, bekräfta att hosten kan nås från din n8n-instans och verifiera att användaren har rättigheter att läsa tabellerna du frågar mot. Om det bara fallerar på vissa frågor kan den genererade SQL:en referera till en tabell eller kolumn som ändrats sedan schemafilen sparades, så kör schemautläsningen igen för att uppdatera den.
Om du kör self-hosted finns ingen körningsgräns (det beror främst på din server och databasen). På n8n Cloud beror kapaciteten på din plans månatliga körningar, och det här arbetsflödet använder normalt en körning per fråga plus den initiala körningen för att bygga schemat.
Ofta ja, eftersom det här inte bara är att ”flytta data från A till B”. Du genererar SQL, validerar den, hanterar schemakontext och returnerar både queryn och resultaten, vilket gör att förgreningslogik spelar roll. n8n är också praktiskt när du vill kunna self-hosta och ha tajtare kontroll över känslig data, särskilt om du kör Ollama lokalt. Zapier och Make kan fungera för enklare automationer, men de blir klumpiga när du behöver validering i flera steg, filhantering och villkorliga vägar i ett och samma flöde. Ärligt talat beror bästa verktyget på volym och hur strikta dina regler för dataåtkomst är. Prata med en automationsexpert om du vill ha en snabb rekommendation.
När detta väl är på plats slutar ”Kan du plocka fram det åt mig?” att vara ett avbrott och blir i stället ett repeterbart, delbart svar. Arbetsflödet tar hand om grovjobbet så att du kan fokusera på besluten.
Kontakta oss
Hör av dig, så diskuterar vi hur just din verksamhet kan dra nytta av alla fantastiska möjligheter som AI skapar.