db: ClickHouse manar database — 11 analytical tables
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
-- ClickHouse: manar database + analytical tables
|
||||
-- Run against existing ClickHouse container
|
||||
-- All tables partitioned by brand_id for multi-tenant isolation
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS manar;
|
||||
|
||||
-- ── Ad Metrics Hourly ────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.ad_metrics_hourly (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
campaign_name String,
|
||||
adgroup_id String,
|
||||
adgroup_name String,
|
||||
hour DateTime,
|
||||
date Date,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64,
|
||||
conv_value Float64,
|
||||
video_views UInt64,
|
||||
ctr Float64 MATERIALIZED if(impressions > 0, clicks / impressions, 0),
|
||||
cpc_micros UInt64 MATERIALIZED if(clicks > 0, cost_micros / clicks, 0),
|
||||
roas Float64 MATERIALIZED if(cost_micros > 0, conv_value / (cost_micros / 1000000), 0)
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, platform, account_id, campaign_id, hour)
|
||||
TTL date + INTERVAL 2 YEAR;
|
||||
|
||||
-- ── Search Term Performance ──────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.search_term_performance (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
adgroup_id String,
|
||||
date Date,
|
||||
search_term String,
|
||||
match_type String,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64,
|
||||
quality_score UInt8
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, date, search_term)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Creative Performance ─────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.creative_performance (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
ad_id String,
|
||||
ad_name String,
|
||||
ad_type String,
|
||||
date Date,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64,
|
||||
headline String,
|
||||
description String
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, ad_id, date)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Device Performance ───────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.device_performance (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
date Date,
|
||||
device String,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, campaign_id, date, device)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Geo Performance ──────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.geo_performance (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
date Date,
|
||||
country_code String,
|
||||
region String,
|
||||
city String,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, campaign_id, date, country_code)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Day Part Performance ─────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.day_part_performance (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
date Date,
|
||||
hour_of_day UInt8,
|
||||
day_of_week UInt8,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, campaign_id, date, hour_of_day)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Placement Performance ────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.placement_performance (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
date Date,
|
||||
placement String,
|
||||
placement_type String,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, campaign_id, date, placement)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Audience Segments ────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.audience_segments (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
campaign_id String,
|
||||
date Date,
|
||||
audience_id String,
|
||||
audience_name String,
|
||||
audience_type String,
|
||||
impressions UInt64,
|
||||
clicks UInt64,
|
||||
cost_micros UInt64,
|
||||
conversions Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, campaign_id, date, audience_id)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Anomaly Events ───────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.anomaly_events (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
entity_type String,
|
||||
entity_id String,
|
||||
metric String,
|
||||
detected_at DateTime DEFAULT now(),
|
||||
date Date,
|
||||
expected_value Float64,
|
||||
actual_value Float64,
|
||||
deviation_pct Float64,
|
||||
severity String,
|
||||
resolved UInt8 DEFAULT 0
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, detected_at)
|
||||
TTL date + INTERVAL 6 MONTH;
|
||||
|
||||
-- ── Competitor Signals ───────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.competitor_signals (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
date Date,
|
||||
keyword String,
|
||||
competitor_domain String,
|
||||
auction_insight_metric String,
|
||||
value Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, date, keyword, competitor_domain)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
|
||||
-- ── Conversion Path ──────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS manar.conversion_path (
|
||||
brand_id String,
|
||||
platform String,
|
||||
account_id String,
|
||||
date Date,
|
||||
conversion_name String,
|
||||
path_length UInt8,
|
||||
days_to_convert UInt16,
|
||||
conversions Float64,
|
||||
conv_value Float64
|
||||
) ENGINE = MergeTree()
|
||||
PARTITION BY (brand_id, toYYYYMM(date))
|
||||
ORDER BY (brand_id, account_id, date, conversion_name)
|
||||
TTL date + INTERVAL 1 YEAR;
|
||||
Reference in New Issue
Block a user