Meer website-statistieken in jouw kleine opslagruimte

Door de website-statistieken te analyseren, krijgen we inzicht in wat er met de site gebeurt. We vergelijken de resultaten met andere kennis over het product of de dienst en verbeteren hiermee onze ervaring.

Wanneer de analyse van de eerste resultaten is voltooid, het informatieoverzicht is gemaakt en conclusies zijn getrokken, begint de volgende fase. Ideeƫn ontstaan: wat gebeurt er als we de gegevens vanuit een ander perspectief bekijken?

Op dit stadium zijn er beperkingen aan de analysetools. Dit is een van de redenen waarom de tool Google Analytics niet voldoende voor mij was, juist vanwege de beperkte mogelijkheden om mijn gegevens te zien en ermee te manipuleren.

Ik heb altijd snel de basisgegevens (master-data) willen uploaden, een ander niveau van aggregatie willen toevoegen of de bestaande waarden anders willen interpreteren.

Dit is gemakkelijk te doen in jouw kleine opslagruimte op basis van het bestand access.log en hiervoor is SQL genoeg.

Dus, op welke vragen wilde ik antwoord vinden?

Wat en wanneer is er veranderd op de site

De geschiedenis van de wijzigingen in de basisgegevens (master-data) is altijd interessant.

Meer website-statistieken in jouw kleine opslagruimte

SQL-query voor rapport

SELECT
	1 AS 'SideStackedBar: Inhoudsupdates per Maand',
	strftime('%m/%Y', datetime(UPDATE_DT, 'unixepoch')) AS 'Dag',
	COUNT(CASE WHEN PAGE_TITLE != 'n.a.' THEN DIM_REQUEST_ID END) AS 'Webpagina-updates',
	COUNT(CASE WHEN PAGE_DESCR = 'IMAGES' THEN DIM_REQUEST_ID END) AS 'Afbeelding uploads',
	COUNT(CASE WHEN PAGE_DESCR = 'VIDEO' THEN DIM_REQUEST_ID END) AS 'Video uploads',
	COUNT(CASE WHEN PAGE_DESCR = 'AUDIO' THEN DIM_REQUEST_ID END) AS 'Audiouploads'
FROM DIM_REQUEST
WHERE PAGE_TITLE != 'n.a.' OF PAGE_DESCR != 'n.a.'
GROUP BY strftime('%m/%Y', datetime(UPDATE_DT, 'unixepoch'))
ORDER BY UPDATE_DT

Bijvoorbeeld, op een bepaald moment werd er zoekmachineoptimalisatie uitgevoerd of werd er nieuwe content op de site toegevoegd, waardoor een toename van het verkeer werd verwacht.

Gebruikersgroepen

Het eenvoudigste voorbeeld van een groep kan een gebruikersagent of de naam van het besturingssysteem zijn.

De meting van gebruikersagents heeft ongeveer duizend records verzameld en ik was benieuwd naar de dynamiek van de verdeling van agents binnen de groep.

Meer website-statistieken in jouw kleine opslagruimte

SQL-query voor rapport

SELECT
	1 AS 'SideStackedBar: Gebruikersagents',
	AGENT_OS AS 'OS',
	SUM(CASE WHEN AGENT_BOT = 'n.a.' THEN 1 ELSE 0 END) AS 'Gebruikersagent van Gebruikers',
	SUM(CASE WHEN AGENT_BOT != 'n.a.' THEN 1 ELSE 0 END) AS 'Gebruikersagent van Bots'
FROM DIM_USER_AGENT
WHERE DIM_USER_AGENT_ID != -1
GROUP BY AGENT_OS
ORDER BY 3 DESC

De meeste verschillende combinaties van agents komen op de site vanuit de wereld van Windows. Onder de onbepaalde bevinden zich dingen zoals WhatsApp, PocketImageCache, PlayStation, SmartTV, enz.

Activiteit van gebruikersgroepen per week

Door sommige groepen samen te voegen, kan de verdeling van hun activiteit worden waargenomen.

Bijvoorbeeld, gebruikers van het Linux-cluster verbruiken meer verkeer op de site dan alle andere.

Meer website-statistieken in jouw kleine opslagruimte

SQL-query voor rapport

SELECT
1 as 'StackedBar: Verkeersvolume per gebruikersbesturingssysteem en per week',
strftime('%W week', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Week',
SUM(CASE WHEN USG.AGENT_OS IN ('Android', 'Linux') THEN FCT.BYTES ELSE 0 END) / 1000 AS 'Android/Linux Gebruikers',
SUM(CASE WHEN USG.AGENT_OS IN ('Windows') THEN FCT.BYTES ELSE 0 END) / 1000 AS 'Windows Gebruikers',
SUM(CASE WHEN USG.AGENT_OS IN ('Macintosh', 'iOS') THEN FCT.BYTES ELSE 0 END) / 1000 AS 'Mac/iOS Gebruikers',
SUM(CASE WHEN USG.AGENT_OS IN ('n.a.', 'BlackBerry') THEN FCT.BYTES ELSE 0 END) / 1000 AS 'Overig'
FROM
  FCT_ACCESS_USER_AGENT_DD FCT,
  DIM_USER_AGENT USG,
  DIM_HTTP_STATUS HST
WHERE FCT.DIM_USER_AGENT_ID = USG.DIM_USER_AGENT_ID
  AND FCT.DIM_HTTP_STATUS_ID = HST.DIM_HTTP_STATUS_ID
  AND USG.AGENT_BOT = 'n.a.' /* alleen gebruikers */
  AND HST.STATUS_GROUP IN ('Successful') /* goede pagina's */
  AND datetime(FCT.EVENT_DT, 'unixepoch') > date('now', '-3 month')
GROUP BY strftime('%W week', datetime(FCT.EVENT_DT, 'unixepoch'))
ORDER BY FCT.EVENT_DT

Intensief verkeer verbruik

Uit de tabel zijn de meest actieve gebruikersgroepen en hun activiteitendag zichtbaar.
De meest actieve behoren tot het Linux-cluster.

Meer website-statistieken in jouw kleine opslagruimte

SQL-query voor rapport

SELECT
1 AS 'Table: User Agent met hoog gebruik',
strftime('%d.%m.%Y', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Dag',
ROUND(1.0 * SUM(FCT.BYTES) / 1000000, 1) AS 'Verkeer MB',
ROUND(1.0 * SUM(FCT.IP_CNT) / SUM(1), 1) AS 'IP's',
ROUND(1.0 * SUM(FCT.REQUEST_CNT) / SUM(1), 1) AS 'Verzoeken',
USA.DIM_USER_AGENT_ID AS 'ID',
MAX(USA.USER_AGENT_NK) AS 'User Agent',
MAX(USA.AGENT_BOT) AS 'Bot'
FROM
FCT_ACCESS_USER_AGENT_DD FCT,
DIM_USER_AGENT USA
WHERE FCT.DIM_USER_AGENT_ID = USA.DIM_USER_AGENT_ID
  AND datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-30 day')
GROUP BY USA.DIM_USER_AGENT_ID, strftime('%d.%m.%Y', datetime(FCT.EVENT_DT, 'unixepoch')) 
ORDER BY SUM(FCT.BYTES) DESC, FCT.EVENT_DT
LIMIT 10

Door gebruik te maken van de attributen dag en ID van de agent, ontstaat de mogelijkheid om snel statistieken per dag voor afzonderlijke gebruikersgroepen te vinden en te volgen. Indien nodig kan gedetailleerde informatie snel worden gevonden in de staging-tabel.

Hoe krijg ik informatie?

Informatie uit het bestand access.log kan nog efficiƫnter worden gemaakt door aanvullende gegevensbronnen te integreren en nieuwe niveaus van aggregatie en groepering in te voeren.

Basisgegevens en entiteiten

Onder basisgegevens valt informatie over entiteiten: webpagina's, afbeeldingen, video's en audio-inhoud; in het geval van een winkel zijn dit producten.

De entiteiten fungeren als dimensies, en het proces van het opslaan van wijzigingen in attributen wordt historisering genoemd. In databases wordt dit proces vaak gerealiseerd in de vorm van langzaam veranderende dimensies (SCD).

Bronnen van basisgegevens kunnen heel divers zijn, daarom moeten ze vrijwel altijd worden geĆÆntegreerd.

Langzaam veranderende dimensie

De meting DIM_REQUEST zal informatie over verzoeken op de site in historische vorm bevatten.

Tabel SCD2

CREATE TABLE DIM_REQUEST ( 
  DIM_REQUEST_ID      INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  DIM_REQUEST_ID_HIST INTEGER NOT NULL DEFAULT -1,
  REQUEST_NK          TEXT NOT NULL DEFAULT 'n.a.', 
  PAGE_TITLE          TEXT NOT NULL DEFAULT 'n.a.',
  PAGE_DESCR          TEXT NOT NULL DEFAULT 'n.a.',
  PAGE_KEYWORDS       TEXT NOT NULL DEFAULT 'n.a.',
  DELETE_FLAG         INTEGER NOT NULL DEFAULT 0,
  UPDATE_DT           INTEGER NOT NULL DEFAULT 0,
  UNIQUE (REQUEST_NK, DIM_REQUEST_ID_HIST)
);
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID) VALUES (-1);

Daarnaast zullen we een weergave creƫren die altijd alle records in de laatste staat weergeeft. Dit is nodig voor het laden van de meting zelf.

Meer website-statistieken in jouw kleine opslagruimte

Actuele weergave SCD2

/* Content: actual view on scd table */
SELECT HI.DIM_REQUEST_ID,
  HI.DIM_REQUEST_ID_HIST,
  HI.REQUEST_NK,
  HI.PAGE_TITLE,
  HI.PAGE_DESCR,
  HI.PAGE_KEYWORDS,
  NK.CNT AS HIST_CNT,
  HI.DELETE_FLAG,
  strftime('%d.%m.%Y %H:%M', datetime(HI.UPDATE_DT, 'unixepoch')) AS UPDATE_DT
FROM
  ( SELECT REQUEST_NK, MAX(DIM_REQUEST_ID) AS DIM_REQUEST_ID, SUM(1) AS CNT
    FROM DIM_REQUEST
    GROUP BY REQUEST_NK
  ) NK,
  DIM_REQUEST HI
WHERE 1 = 1
  AND NK.REQUEST_NK = HI.REQUEST_NK
  AND NK.DIM_REQUEST_ID = HI.DIM_REQUEST_ID;

En de weergave waar historische informatie voor elk record is verzameld. Dit is nodig om historisch accurate relaties met feiten op te bouwen.

Meer website-statistieken in jouw kleine opslagruimte

Historische weergave SCD2

/* Content: actual view on scd table */
SELECT SCD.DIM_REQUEST_ID,
  SCD.DIM_REQUEST_ID_HIST,
  SCD.REQUEST_NK,
  SCD.PAGE_TITLE,
  SCD.PAGE_DESCR,
  SCD.PAGE_KEYWORDS,
  SCD.DELETE_FLAG,
  CASE
    WHEN HIS.UPDATE_DT IS NULL
    THEN 1
    ELSE 0 END ACTIVE_FLAG,
  SCD.DIM_REQUEST_ID_HIST AS ID_FROM,
  SCD.DIM_REQUEST_ID AS ID_TO,
  CASE
    WHEN SCD.DIM_REQUEST_ID_HIST=-1
    THEN 3600
    ELSE IFNULL(SCD.UPDATE_DT,3600)
  END AS TIME_FROM,
  CASE
    WHEN HIS.UPDATE_DT IS NULL
    THEN 253370764800
    ELSE HIS.UPDATE_DT
  END AS TIME_TO,
  CASE
    WHEN SCD.DIM_REQUEST_ID_HIST=-1
    THEN STRFTIME('%d.%m.%Y %H:%M', DATETIME(3600, 'unixepoch'))
    ELSE STRFTIME('%d.%m.%Y %H:%M', DATETIME(IFNULL(SCD.UPDATE_DT,3600), 'unixepoch'))
  END AS ACTIVE_FROM,
  CASE
    WHEN HIS.UPDATE_DT IS NULL
    THEN STRFTIME('%d.%m.%Y %H:%M', DATETIME(253370764800, 'unixepoch'))
    ELSE STRFTIME('%d.%m.%Y %H:%M', DATETIME(HIS.UPDATE_DT, 'unixepoch'))
  END AS ACTIVE_TO
FROM
  DIM_REQUEST SCD
  LEFT OUTER JOIN DIM_REQUEST HIS
  ON SCD.REQUEST_NK = HIS.REQUEST_NK AND SCD.DIM_REQUEST_ID = HIS.DIM_REQUEST_ID_HIST;

Gegevensaggregatie

Comprimeren (aggregatie) stelt je in staat om gegevens op een hoger niveau te evalueren en afwijkingen en trends te ontdekken die niet zichtbaar zijn in gedetailleerde rapporten.

Bijvoorbeeld, in de meting met statuscodes DIM_HTTP_STATUS voegen we een groep toe:

STATUS / GROEP
0xx / n.a.
1xx / Informatief
2xx / Succesvol
3xx / Redirectie
4xx / Clientfout
5xx / Serverfout

De meting van gebruikersagenten DIM_USER_AGENT zal de attributen AGENT_OS en AGENT_BOT bevatten, die verantwoordelijk zijn voor de groepen. Deze kunnen tijdens het ETL-proces worden ingevuld:

Laden van DIM_USER_AGENT

/* Propagate the user agent from access log */
INSERT INTO DIM_USER_AGENT (USER_AGENT_NK, AGENT_OS, AGENT_ENGINE, AGENT_DEVICE, AGENT_BOT, UPDATE_DT)
WITH CLS AS (
	SELECT BROWSER
	FROM STG_ACCESS_LOG WHERE LENGTH(BROWSER)>1
	GROUP BY BROWSER
)
SELECT
	CLS.BROWSER AS USER_AGENT_NK,
	CASE
	WHEN INSTR(CLS.BROWSER,'Macintosh')>0
		THEN 'Macintosh'
	WHEN INSTR(CLS.BROWSER,'iPhone')>0
			 OR INSTR(CLS.BROWSER,'iPad')>0
			 OR INSTR(CLS.BROWSER,'iPod')>0
			 OR INSTR(CLS.BROWSER,'Apple TV')>0
			 OR INSTR(CLS.BROWSER,'Darwin')>0
		THEN 'iOS'
	WHEN INSTR(CLS.BROWSER,'Android')>0
		THEN 'Android'
	WHEN INSTR(CLS.BROWSER,'X11;')>0 OR INSTR(CLS.BROWSER,'Wayland;')>0 OR INSTR(CLS.BROWSER,'linux-gnu')>0
		THEN 'Linux'
	WHEN INSTR(CLS.BROWSER,'BB10;')>0 OR INSTR(CLS.BROWSER,'BlackBerry')>0
		THEN 'BlackBerry'
	WHEN INSTR(CLS.BROWSER,'Windows')>0
		THEN 'Windows'
	ELSE 'n.a.' END AS AGENT_OS, -- OS
	CASE
	WHEN INSTR(CLS.BROWSER,'AppleCoreMedia')>0
		THEN 'AppleWebKit'
	WHEN INSTR(CLS.BROWSER,') ')>1 AND LENGTH(CLS.BROWSER)>INSTR(CLS.BROWSER,') ')
		THEN COALESCE(SUBSTR(CLS.BROWSER, INSTR(CLS.BROWSER,') ')+2, LENGTH(CLS.BROWSER) - INSTR(CLS.BROWSER,') ')-1), 'N/A')
	ELSE 'n.a.' END AS AGENT_ENGINE, -- Engine
	CASE
	WHEN INSTR(CLS.BROWSER,'iPhone')>0
		THEN 'iPhone'
	WHEN INSTR(CLS.BROWSER,'iPad')>0
		THEN 'iPad'
	WHEN INSTR(CLS.BROWSER,'iPod')>0
		THEN 'iPod'
	WHEN INSTR(CLS.BROWSER,'Apple TV')>0
		THEN 'Apple TV'
	WHEN INSTR(CLS.BROWSER,'Android ')>0 AND INSTR(CLS.BROWSER,'Build')>0
		THEN COALESCE(SUBSTR(CLS.BROWSER, INSTR(CLS.BROWSER,'Android '), INSTR(CLS.BROWSER,'Build')-INSTR(CLS.BROWSER,'Android ')), 'n.a.')
	WHEN INSTR(CLS.BROWSER,'Android ')>0 AND INSTR(CLS.BROWSER,'MIUI')>0
		THEN COALESCE(SUBSTR(CLS.BROWSER, INSTR(CLS.BROWSER,'Android '), INSTR(CLS.BROWSER,'MIUI')-INSTR(CLS.BROWSER,'Android ')), 'n.a.')
	ELSE 'n.a.' END AS AGENT_DEVICE, -- Device
	CASE
	WHEN INSTR(LOWER(CLS.BROWSER),'yandex.com')>0
		THEN 'yandex'
	WHEN INSTR(LOWER(CLS.BROWSER),'googlebot')>0
		THEN 'google'
	WHEN INSTR(LOWER(CLS.BROWSER),'bingbot')>0
		THEN 'microsoft'
	WHEN INSTR(LOWER(CLS.BROWSER),'ahrefsbot')>0
		THEN 'ahrefs'
	WHEN INSTR(LOWER(CLS.BROWSER),'jobboersebot')>0 OR INSTR(LOWER(CLS.BROWSER),'jobkicks')>0
		THEN 'job.de'
	WHEN INSTR(LOWER(CLS.BROWSER),'mail.ru')>0
		THEN 'mail.ru'
	WHEN INSTR(LOWER(CLS.BROWSER),'baiduspider')>0
		THEN 'baidu'
	WHEN INSTR(LOWER(CLS.BROWSER),'mj12bot')>0
		THEN 'majestic-12'
	WHEN INSTR(LOWER(CLS.BROWSER),'duckduckgo')>0
		THEN 'duckduckgo'
	WHEN INSTR(LOWER(CLS.BROWSER),'bytespider')>0
		THEN 'bytespider'
	WHEN INSTR(LOWER(CLS.BROWSER),'360spider')>0
		THEN 'so.360.cn'
	WHEN INSTR(LOWER(CLS.BROWSER),'compatible')>0 OR INSTR(LOWER(CLS.BROWSER),'http')>0
		OR INSTR(LOWER(CLS.BROWSER),'libwww')>0 OR INSTR(LOWER(CLS.BROWSER),'spider')>0
		OR INSTR(LOWER(CLS.BROWSER),'java')>0 OR INSTR(LOWER(CLS.BROWSER),'python')>0
		OR INSTR(LOWER(CLS.BROWSER),'robot')>0 OR INSTR(LOWER(CLS.BROWSER),'curl')>0 OR INSTR(LOWER(CLS.BROWSER),'wget')>0
		THEN 'other'
	ELSE 'n.a.' END AS AGENT_BOT, -- Bot
	STRFTIME('%s','now') AS UPDATE_DT
FROM CLS
LEFT OUTER JOIN DIM_USER_AGENT TRG
ON CLS.BROWSER = TRG.USER_AGENT_NK
WHERE TRG.DIM_USER_AGENT_ID IS NULL

Gegevensintegratie

Bevat de organisatie van de gegevensoverdracht van het besturingssysteem naar het rapport. Hiervoor moet een stagingtabel met een structuur die gelijk is aan de bron worden gemaakt.

In de staging komt informatie over webpagina's uit de back-up van de CMS in de vorm van invoegverzoeken.

Het laden van historische tabel DIM_REQUEST met basisgegevens gebeurt in drie stappen: laden van nieuwe sleutels en attributen, bijwerken van bestaande en vastleggen van verwijderde records.

Laden van nieuwe records SCD2

/* Load request table SCD from master data */
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID_HIST, REQUEST_NK, PAGE_TITLE, PAGE_DESCR, PAGE_KEYWORDS, DELETE_FLAG, UPDATE_DT)
WITH CLS  AS ( -- prepare keys
	SELECT
	'/' || NAME AS REQUEST_NK,
	TITLE       AS PAGE_TITLE,
	CASE WHEN DESCRIPTION = '' OR DESCRIPTION IS NULL
	     THEN 'n.a.' ELSE DESCRIPTION
	END AS PAGE_DESCR,
	CASE WHEN KEYWORDS = '' OR KEYWORDS IS NULL
	     THEN 'n.a.' ELSE KEYWORDS
	END AS PAGE_KEYWORDS
	FROM STG_CMS_MENU
	WHERE CONTENT_TYPE != 'folder' -- only web pages
	  AND PAGE_TITLE != 'n.a.' -- master data which make sense
)
/* new records from stage: CLS */
SELECT
	-1 AS DIM_REQUEST_ID_HIST,
	CLS.REQUEST_NK,
	CLS.PAGE_TITLE,
	CLS.PAGE_DESCR,
	CLS.PAGE_KEYWORDS,
	0 AS DELETE_FLAG,
	STRFTIME('%s','now') AS UPDATE_DT
FROM CLS
LEFT OUTER JOIN
 (
	SELECT
	DIM_REQUEST_ID,
	REQUEST_NK,
	PAGE_TITLE,
	PAGE_DESCR,
	PAGE_KEYWORDS
	FROM DIM_REQUEST_V_ACT
) TRG ON CLS.REQUEST_NK = TRG.REQUEST_NK
WHERE TRG.REQUEST_NK IS NULL -- no such record in data mart

Bijwerken van attributen SCD2

/* Load request table SCD from master data */
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID_HIST, REQUEST_NK, PAGE_TITLE, PAGE_DESCR, PAGE_KEYWORDS, DELETE_FLAG, UPDATE_DT)
WITH CLS  AS ( -- prepare keys
	SELECT
	'/' || NAME AS REQUEST_NK,
	TITLE       AS PAGE_TITLE,
	CASE WHEN DESCRIPTION = '' OR DESCRIPTION IS NULL
	     THEN 'n.a.' ELSE DESCRIPTION
	END AS PAGE_DESCR,
	CASE WHEN KEYWORDS = '' OR KEYWORDS IS NULL
	     THEN 'n.a.' ELSE KEYWORDS
	END AS PAGE_KEYWORDS
	FROM STG_CMS_MENU
	WHERE CONTENT_TYPE != 'folder' -- only web pages
	  AND PAGE_TITLE != 'n.a.' -- master data which make sense
)
/* updated records from stage: CLS and build reference to history: HIST */
SELECT
	HIST.DIM_REQUEST_ID AS DIM_REQUEST_ID_HIST,
	HIST.REQUEST_NK,
	CLS.PAGE_TITLE,
	CLS.PAGE_DESCR,
	CLS.PAGE_KEYWORDS,
	0 AS DELETE_FLAG,
	STRFTIME('%s','now') AS UPDATE_DT
FROM CLS,
     DIM_REQUEST_V_ACT TRG,
     DIM_REQUEST HIST
WHERE CLS.REQUEST_NK = TRG.REQUEST_NK
  AND TRG.DIM_REQUEST_ID = HIST.DIM_REQUEST_ID
  AND ( CLS.PAGE_TITLE != HIST.PAGE_TITLE /* changes only */
     OR CLS.PAGE_DESCR != HIST.PAGE_DESCR
     OR CLS.PAGE_KEYWORDS != HIST.PAGE_KEYWORDS )

Verwijderde records SCD2

/* Load request table SCD from master data */
INSERT INTO DIM_REQUEST (DIM_REQUEST_ID_HIST, REQUEST_NK, PAGE_TITLE, PAGE_DESCR, PAGE_KEYWORDS, DELETE_FLAG, UPDATE_DT)
WITH CLS  AS ( -- prepare keys
	SELECT
	'/' || NAME AS REQUEST_NK,
	TITLE       AS PAGE_TITLE
	FROM STG_CMS_MENU
	WHERE CONTENT_TYPE != 'folder' -- only web pages
	  AND PAGE_TITLE != 'n.a.' -- master data which make sense
)
/*  deleted records in data mart: TRG */
SELECT
	TRG.DIM_REQUEST_ID AS DIM_REQUEST_ID_HIST,
	TRG.REQUEST_NK,
	TRG.PAGE_TITLE,
	TRG.PAGE_DESCR,
	TRG.PAGE_KEYWORDS,
	1 AS DELETE_FLAG,
	STRFTIME('%s','now') AS UPDATE_DT
FROM (
	SELECT
	DIM_REQUEST_ID,
	REQUEST_NK,
	PAGE_TITLE,
	PAGE_DESCR,
	PAGE_KEYWORDS
	FROM DIM_REQUEST_V_ACT
	WHERE PAGE_TITLE != 'n.a.' -- track master data only
	  AND DELETE_FLAG = 0 -- not already deleted
) TRG
LEFT OUTER JOIN CLS ON TRG.REQUEST_NK = CLS.REQUEST_NK
WHERE CLS.REQUEST_NK IS NULL -- no such record in stage

Elke gegevensbron moet worden vergezeld van een formele beschrijving, bijvoorbeeld in een bestand readme.txt:

Ontvanger van gegevens formeel/technisch: naam, e-mailadres
Leverancier van gegevens formeel/technisch: naam, e-mailadres
Gegevensbron: bestandspad, namen van services
Informatie over toegang tot gegevens: gebruikers en wachtwoorden

Het schema van gegevensbeweging zal helpen in het proces van onderhoud en updates, bijvoorbeeld in tekstvorm:

Bestand verplaatsen. Bron: ftp.domain.net: /logs/access.log Doel: /var/www/access.log
Lezen in de staging. Doel: STG_ACCESS_LOG
Uploaden en transformeren. Doel: FCT_ACCESS_REQUEST_REF_HH
Uploaden en transformeren. Doel: FCT_ACCESS_USER_AGENT_DD
Rapport. Doel: /var/www/report.html

Uitslag

Dit artikel beschrijft mechanismen zoals de integratie van basisgegevens en de invoering van nieuwe aggregatieniveaus. Deze zijn nodig bij het opbouwen van datawarehouses om meer inzichten te verkrijgen en de kwaliteit van informatie te verbeteren.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster