# Business intelligence

## Vad det är

Business intelligence, i dagligt tal förkortat BI, är arbetet med att göra en
organisations egna data till rapporter, dashboards och analyser som de som
fattar besluten kan agera på. Som förled används nästan alltid förkortningen,
som i BI-verktyg.

Uttrycket är äldre än mjukvaran. I oktober 1958 publicerade IBM Journal of
Research and Development en artikel av H. P. Luhn med titeln ”A Business
Intelligence System”. Luhn beskrev ett maskinellt system som skulle ta de
dokument en organisation tar emot eller själv skriver, göra ett automatiskt
sammandrag av vart och ett, beskriva det med ett mönster av dess ord och skicka
det till de ställen i organisationen — Luhn kallade dem action points — vars
intresseprofil stämde. Ett sådant ställe kunde vara en enskild person, en grupp,
en avdelning eller en hel division. Han gav ordet business en medvetet vid
betydelse, all organiserad verksamhet från vetenskap och handel till juridik,
förvaltning och försvar, och förstod intelligence som förmågan att se hur de
fakta man har framför sig hänger ihop, tillräckligt väl för att styra handlandet
mot ett mål. När han hade gått igenom teknikerna gav han helheten ett namn: ”We
call this a Business Intelligence System.”

Luhns material var text. Dagens BI arbetar mest med siffror i tabeller, och
Kimball Groups beskrivning av ett datalager- och BI-system visar det vanliga
upplägget. I bakrummet (back room) hämtas data från källsystemen, tvättas, görs
enhetliga och läses in. I det främre rummet (front room) presenteras de, ordnade
efter affärsprocess och lagrade på den mest detaljerade nivån, med aggregerade
sammanfattningar tillagda för att det ska gå snabbare. Överst ligger
BI-applikationerna: ad hoc-frågor, standardrapporter, dashboards och scorecards
samt tyngre applikationer för analys och datautvinning.

Det som binder ihop de två betydelserna är Luhns fråga: vem behöver veta det
här, och hur når det fram till dem i en form som de faktiskt läser?

## Varför det spelar roll

Varje organisation styrs redan efter siffror. Frågan är om siffrorna stämmer
överens. När säljavdelningen räknar en order från den dag avtalet skrivs under
och ekonomiavdelningen från den dag fakturan skickas, kommer de två
avdelningarna till samma möte med var sin intäktssiffra, och mötet går åt till
skillnaden i stället för beslutet. Ett BI-system tjänar in sin kostnad genom att
fastställa en definition per nyckeltal, beräkna det på ett ställe och visa samma
siffra för alla som frågar.

Luhns diagnos från 1958 passar fortfarande de flesta delade rapportmappar. Han
såg organisationer sprida information brett för att vara på den säkra sidan och
konstaterade att mottagarna drunknade i papper, så att risken att ingenting
nådde fram blev stor. En dashboard med fyrtio diagram gör samma sak på en skärm.
Luhns botemedel var urval. Varje mottagare fick först bara löpnummer, titel och
författare för de dokument som valts ut åt den. Sedan kunde den slå numren på en
telefon för att få sammandragen och begära dem den ville ha i sin helhet. Varje
gång den tog emot ett dokument uppdaterades profilen, så urvalet blev bättre ju
mer det användes. En bra rapport i dag fungerar likadant: den utgår från en
person och ett beslut och visar de få siffror beslutet hänger på.

Det finns också en praktisk sida. Databasen bakom en applikation är byggd för
dess många små läsningar och skrivningar. En fråga som läser ett helt års ordrar
konkurrerar med de skrivningarna när den körs på samma ställe, och det är ett
skäl till att BI-data oftast ligger i ett separat lager som fylls vid fasta
tider. Att hålla det lagret på den mest detaljerade nivån, som Kimball
beskriver, avgör vilka frågor som fortfarande går att besvara nästa år utan att
gå tillbaka till källorna.

## Så ser det ut i praktiken

En typisk BI-fråga: omsättningen under tredje kvartalet 2026 fördelad på region
och produkt, med en delsumma för varje region och en totalsumma. Med en tabell
`sales` som har en rad per försäljning, med `sold_on`, `region`, `product` och
`amount`, besvarar standard-SQL det i en enda fråga:

```sql
SELECT region,
       product,
       sum(amount)               AS revenue,
       GROUPING(region, product) AS level
FROM   sales
WHERE  sold_on >= DATE '2026-07-01'
AND    sold_on <  DATE '2026-10-01'
GROUP  BY ROLLUP (region, product)
ORDER  BY GROUPING(region), region, GROUPING(product), product;
```

Med en handfull exempelrader blir resultatet:

```text
 region | product | revenue | level
--------+---------+---------+-------
 North  | Boots   |    1200 |     0
 North  | Jackets |     800 |     0
 North  |         |    2000 |     1
 South  | Boots   |     500 |     0
 South  | Jackets |    1500 |     0
 South  |         |    2000 |     1
        |         |    4000 |     3
```

`ROLLUP (region, product)` är en kortform för
`GROUPING SETS ((region, product), (region), ())`: hela listan, varje kortare
prefix av den och till sist den tomma mängden, som summerar alla rader.
PostgreSQL-dokumentationen beskriver den som det vanliga verktyget för
hierarkiska data, till exempel lön per avdelning, per division och för hela
företaget. `CUBE (region, product)` skulle i stället gruppera efter alla
delmängder och därmed lägga till en summa för varje produkt över alla regioner.

En kolumn som inte ingår i radens grupperingsmängd kommer tillbaka som NULL, och
därför har delsummeraderna tomma fält. `GROUPING(region, product)` talar om
vilka kolumner det gäller. Den returnerar en bitmask med en bit per argument,
med det sista argumentet i den lägsta biten, och en bit är 1 när kolumnen inte
var grupperad för raden. Alltså markerar 0 en detaljrad, 1 en delsumma för en
region (produkten är inte grupperad) och 3 totalsumman (ingen av dem är
grupperad). En rapport läser `level` för att avgöra vilka rader som ska stå i
fetstil.

Företagets
[tjänst för dataanalys och BI-dashboards](/sv/services/data-analytics-bi/)
beskriver målet som dashboards och rapporter som visar de få siffror ett beslut
faktiskt hänger på, uppdaterade utan att någon behöver be om det. En fråga som
den här är lagret under en sådan rapport: summorna beräknas en gång, i
databasen, och dashboarden ritar bara upp dem.

## Var det går fel

**Två siffror under samma namn.** Intäkter, aktiv kund och kundbortfall har var
och en flera rimliga definitioner, och varje rapport som räknar själv väljer en.
Skriv ner varje nyckeltal en gång, med vad det räknar, från vilken källa och per
vilket datum, och beräkna det i databasen, till exempel som en vy, i stället för
i formlerna i varje rapport. Kimball kallar den språkliga delen affärsmetadata:
vilka data som finns, var de kommer ifrån och vad de betyder.

**Allt skickat till alla.** En dashboard med dussintals diagram och en sändlista
med hela avdelningen återskapar den flod Luhn ville stoppa. Börja med en
namngiven person och det beslut hen fattar, visa de siffror beslutet kräver och
lägg ner de rapporter som ingen har öppnat på ett kvartal.

**Rapporter som gör applikationen långsam.** En tung fråga mot primärdatabasen i
ett system i drift konkurrerar med kunderna som använder det. Kör rapporteringen
mot en läsreplik eller i ett separat datalager som fylls vid fasta tider.
Aggregat som är dyra att beräkna och efterfrågas ofta kan läggas i en
materialiserad vy som uppdateras efter varje inläsning.

**Summor byggda av summor.** Medelvärdet av varje regions genomsnittliga
ordervärde är inte företagets genomsnittliga ordervärde, om inte alla regioner
har lika många ordrar. Antalet unika kunder per månad kan inte summeras till ett
kvartal, eftersom en kund som handlade både i juli och i augusti räknas två
gånger. Behåll detaljraderna och aggregera varje nivå från dem.
Grupperingsmängder gör precis det: varje nivå i frågan ovan beräknas från
försäljningsraderna, inte från nivån under.

**Ett tomt fält med två betydelser.** Lägg till en försäljning där regionen är
okänd, så ger frågan ovan en detaljrad med tom region, en delsumma för den med
två tomma fält och en totalsumma, också med två tomma fält. Med `CUBE` blir det
värre: två rader visar tom region och Boots, den ena för Boots sålda där
regionen är okänd och den andra för Boots i alla regioner tillsammans.
PostgreSQL-dokumentationen varnar för att en NULL i data inte går att skilja
från den NULL som står för en kolumn som har grupperats bort. Använd
`GROUPING()`, aldrig `IS NULL`, för att hitta delsummerader, och ge saknade
värden en synlig etikett som ”okänd” när data läses in.

**Gårdagens siffror lästa som dagens.** När en nattlig inläsning misslyckas
fortsätter dashboarden att visa de senaste bra siffrorna, och ingenting på
skärmen säger att de är gamla. Skriv ut tidpunkten för den senaste lyckade
inläsningen på varje rapport, och låt övervakningen skicka ett larm till en
namngiven person när en planerad inläsning inte blir klar.

## Läs mer

- [A Business Intelligence System](https://doi.org/10.1147/rd.24.0314) — H. P.
  Luhns artikel i IBM Journal of Research and Development, oktober 1958, där
  uttrycket kommer ifrån.
- [Kimball Technical DW/BI System Architecture](https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/technical-dw-bi-system-architecture/)
  — Kimball Groups genomgång av bakrummet, presentationsytan, BI-applikationerna
  och metadata.
- [Table Expressions](https://www.postgresql.org/docs/current/queries-table-expressions.html)
  — PostgreSQL:s referens för `GROUPING SETS`, `ROLLUP` och `CUBE`, och för hur
  NULL står i stället för en kolumn som inte är grupperad.
- [Aggregate Functions](https://www.postgresql.org/docs/current/functions-aggregate.html)
  — funktionen `GROUPING` och dess bitmask, med ett genomräknat exempel.

<https://engineer.company/sv/glossary/business-intelligence/>
