# Business intelligence

## Hva det er

Business intelligence, til daglig forkortet BI, er arbeidet med å gjøre en
organisasjons egne data om til rapporter, dashbord og analyser som de som tar
beslutningene, kan handle på. Som førsteledd brukes nesten alltid forkortelsen,
som i BI-verktøy.

Uttrykket er eldre enn programvaren. I oktober 1958 trykket IBM Journal of
Research and Development en artikkel av H. P. Luhn med tittelen «A Business
Intelligence System». Luhn beskrev et maskinelt system som skulle ta dokumentene
en organisasjon mottar eller skriver selv, lage et automatisk sammendrag av
hvert enkelt, beskrive det med et mønster av ordene i det og sende det til de
stedene i organisasjonen — Luhn kalte dem action points — der interesseprofilen
passet. Et slikt sted kunne være én person, en gruppe, en avdeling eller en hel
divisjon. Han ga ordet business en bevisst vid betydning, all organisert
virksomhet fra vitenskap og handel til jus, forvaltning og forsvar, og forsto
intelligence som evnen til å se hvordan de foreliggende faktaene henger sammen,
godt nok til å styre handlingen mot et mål. Etter å ha gått gjennom teknikkene
ga han helheten et navn: «We call this a Business Intelligence System.»

Luhns materiale var tekst. Dagens BI arbeider mest med tall i tabeller, og
Kimball Groups beskrivelse av et datavarehus- og BI-system viser den vanlige
oppbygningen. I bakrommet (back room) hentes data fra kildesystemene, vaskes,
gjøres ensartet og lastes inn. I frontrommet (front room) presenteres de, ordnet
etter forretningsprosess og lagret på det mest detaljerte nivået, med aggregerte
sammendrag lagt til for å gjøre det raskere. Øverst ligger BI-applikasjonene: ad
hoc-spørringer, standardrapporter, dashbord, scorecards og tyngre applikasjoner
for analyse og datautvinning.

Det som binder de to betydningene sammen, er Luhns spørsmål: hvem trenger å vite
dette, og hvordan når det fram til dem i en form de faktisk leser?

## Hvorfor det er viktig

Enhver organisasjon styres allerede etter tall. Spørsmålet er om tallene stemmer
overens. Når salgsavdelingen regner en ordre fra dagen kontrakten signeres, og
økonomiavdelingen fra dagen fakturaen sendes, kommer de to avdelingene til samme
møte med hvert sitt omsetningstall, og møtet går med til forskjellen i stedet
for beslutningen. Et BI-system tjener inn kostnaden ved å fastsette én
definisjon per nøkkeltall, beregne det ett sted og vise det samme tallet til
alle som spør.

Luhns diagnose fra 1958 passer fortsatt på de fleste felles rapportmapper. Han
så at organisasjoner spredte informasjon vidt for å være på den sikre siden, og
bemerket at mottakerne druknet i papir, slik at sjansen for at ingenting nådde
fram, ble stor. Et dashbord med førti diagrammer gjør det samme på en skjerm.
Luhns botemiddel var utvelgelse. Hvert mottakersted fikk først bare løpenummer,
tittel og forfatter for dokumentene som var valgt ut til det. Deretter kunne det
slå numrene på en telefon for å få sammendragene, og be om dem det ville ha, i
full lengde. Hver gang det tok imot et dokument, ble profilen oppdatert, så
utvelgelsen ble bedre med bruk. En god rapport i dag virker på samme måte: den
tar utgangspunkt i en person og en beslutning og viser de få tallene
beslutningen hviler på.

Det finnes også en praktisk side. Databasen bak en applikasjon er bygd for dens
mange små lesinger og skrivinger. Et spørsmål som leser et helt års ordrer,
konkurrerer med de skrivingene når det kjører på samme sted, og det er én grunn
til at BI-data vanligvis ligger i et eget lager som fylles etter en fast plan. Å
holde det lageret på det mest detaljerte nivået, slik Kimball beskriver, avgjør
hvilke spørsmål man fortsatt kan besvare neste år uten å gå tilbake til kildene.

## Slik ser det ut i praksis

Et typisk BI-spørsmål: omsetningen i tredje kvartal 2026 fordelt på region og
produkt, med en delsum for hver region og en totalsum. Med en tabell `sales` som
har én rad per salg, med `sold_on`, `region`, `product` og `amount`, besvarer
standard SQL det i én spørring:

```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 håndfull eksempelrader gir den:

```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)` er en kortform for
`GROUPING SETS ((region, product), (region), ())`: hele listen, hvert kortere
prefiks av den og til slutt den tomme mengden, som summerer alle radene.
PostgreSQL-dokumentasjonen omtaler den som det vanlige verktøyet for hierarkiske
data, for eksempel lønn per avdeling, per divisjon og for hele selskapet.
`CUBE (region, product)` ville i stedet gruppert etter alle delmengder og dermed
lagt til en sum for hvert produkt på tvers av regionene.

En kolonne som ikke inngår i radens grupperingsmengde, kommer tilbake som NULL,
og derfor har delsumradene tomme felter. `GROUPING(region, product)` forteller
hvilke kolonner det gjelder. Den returnerer en bitmaske med én bit per argument,
med det siste argumentet i den laveste biten, og en bit er 1 når kolonnen ikke
var gruppert for raden. Altså markerer 0 en detaljrad, 1 en delsum for en region
(produktet er ikke gruppert) og 3 totalsummen (ingen av dem er gruppert). En
rapport leser `level` for å avgjøre hvilke rader som skal stå i fet skrift.

Selskapets
[tjeneste for dataanalyse og BI-dashbord](/nb/services/data-analytics-bi/)
beskriver målet som dashbord og rapporter som viser de få tallene en beslutning
faktisk hviler på, oppdatert uten at noen må be om det. En spørring som denne er
laget under en slik rapport: summene beregnes én gang, i databasen, og
dashbordet tegner dem bare.

## Hvor det går galt

**To tall under samme navn.** Omsetning, aktiv kunde og kundefrafall har hver
flere rimelige definisjoner, og hver rapport som regner selv, velger én. Skriv
ned hvert nøkkeltall én gang, med hva det teller, fra hvilken kilde og per
hvilken dato, og beregn det i databasen, for eksempel som en visning, i stedet
for i formlene i hver enkelt rapport. Kimball kaller den språklige delen
forretningsmetadata: hvilke data som finnes, hvor de kommer fra, og hva de
betyr.

**Alt sendt til alle.** Et dashbord med flere dusin diagrammer og en
mottakerliste med hele avdelingen gjenskaper flommen Luhn ville stanse. Begynn
med en navngitt person og beslutningen vedkommende tar, vis tallene beslutningen
krever, og legg ned rapportene ingen har åpnet på et kvartal.

**Rapporter som gjør applikasjonen treg.** En tung spørring mot primærdatabasen
i et system i drift konkurrerer med kundene som bruker det. Kjør rapporteringen
mot en lesereplika eller i et eget datavarehus som fylles etter en fast plan.
Aggregater som er dyre å beregne og etterspørres ofte, kan legges i en
materialisert visning som oppdateres etter hver innlasting.

**Summer bygd av summer.** Gjennomsnittet av hver regions gjennomsnittlige
ordreverdi er ikke selskapets gjennomsnittlige ordreverdi, med mindre alle
regionene har like mange ordrer. Antallet ulike kunder per måned kan ikke legges
sammen til et kvartal, for en kunde som handlet både i juli og i august, telles
to ganger. Behold detaljradene, og aggreger hvert nivå fra dem.
Grupperingsmengder gjør nettopp det: hvert nivå i spørringen ovenfor beregnes
fra salgsradene, ikke fra nivået under.

**Et tomt felt med to betydninger.** Legg til ett salg der regionen er ukjent,
så gir spørringen ovenfor en detaljrad med tom region, en delsum for den med to
tomme felter og en totalsum, også med to tomme felter. Med `CUBE` blir det
verre: to rader viser tom region og Boots, den ene for Boots solgt der regionen
er ukjent, og den andre for Boots i alle regioner til sammen.
PostgreSQL-dokumentasjonen advarer om at en NULL i dataene ikke kan skilles fra
NULL-en som står for en kolonne som er gruppert bort. Bruk `GROUPING()`, aldri
`IS NULL`, for å finne delsumrader, og gi manglende verdier en synlig betegnelse
som «ukjent» når dataene lastes inn.

**Gårsdagens tall lest som dagens.** Når en nattlig innlasting feiler,
fortsetter dashbordet å vise de siste gode tallene, og ingenting på skjermen
sier at de er gamle. Skriv tidspunktet for siste vellykkede innlasting på hver
rapport, og la overvåkingen sende et varsel til en navngitt person når en
planlagt innlasting ikke blir ferdig.

## Les mer

- [A Business Intelligence System](https://doi.org/10.1147/rd.24.0314) — H. P.
  Luhns artikkel i IBM Journal of Research and Development, oktober 1958, der
  uttrykket kommer fra.
- [Kimball Technical DW/BI System Architecture](https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/technical-dw-bi-system-architecture/)
  — Kimball Groups gjennomgang av bakrommet, presentasjonsområdet,
  BI-applikasjonene og metadataene.
- [Table Expressions](https://www.postgresql.org/docs/current/queries-table-expressions.html)
  — PostgreSQLs referanse for `GROUPING SETS`, `ROLLUP` og `CUBE`, og for
  hvordan NULL står i stedet for en kolonne som ikke er gruppert.
- [Aggregate Functions](https://www.postgresql.org/docs/current/functions-aggregate.html)
  — funksjonen `GROUPING` og bitmasken dens, med et gjennomregnet eksempel.

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