-- Runs the steps in https://docs.microsoft.com/en-us/azure/postgresql/tutorial-design-database-hyperscale-multi-tenant
SET citus.shard_replication_factor TO 1;
CREATE TABLE companies (
  id bigserial PRIMARY KEY,
  name text NOT NULL,
  image_url text,
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL
);
CREATE TABLE campaigns (
  id bigserial,
  company_id bigint REFERENCES companies (id),
  name text NOT NULL,
  cost_model text NOT NULL,
  state text NOT NULL,
  monthly_budget bigint,
  blacklisted_site_urls text[],
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL,
  PRIMARY KEY (company_id, id)
);
CREATE TABLE ads (
  id bigserial,
  company_id bigint,
  campaign_id bigint,
  name text NOT NULL,
  image_url text,
  target_url text,
  impressions_count bigint DEFAULT 0,
  clicks_count bigint DEFAULT 0,
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL,
  PRIMARY KEY (company_id, id),
  FOREIGN KEY (company_id, campaign_id)
    REFERENCES campaigns (company_id, id)
);
CREATE TABLE clicks (
  id bigserial,
  company_id bigint,
  ad_id bigint,
  clicked_at timestamp without time zone NOT NULL,
  site_url text NOT NULL,
  cost_per_click_usd numeric(20,10),
  user_ip inet NOT NULL,
  user_data jsonb NOT NULL,
  PRIMARY KEY (company_id, id),
  FOREIGN KEY (company_id, ad_id)
    REFERENCES ads (company_id, id)
);
CREATE TABLE impressions (
  id bigserial,
  company_id bigint,
  ad_id bigint,
  seen_at timestamp without time zone NOT NULL,
  site_url text NOT NULL,
  cost_per_impression_usd numeric(20,10),
  user_ip inet NOT NULL,
  user_data jsonb NOT NULL,
  PRIMARY KEY (company_id, id),
  FOREIGN KEY (company_id, ad_id)
    REFERENCES ads (company_id, id)
);
begin;
SELECT create_distributed_table('companies',   'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('campaigns',   'company_id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

rollback;
SELECT create_distributed_table('companies',   'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('campaigns',   'company_id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('ads',         'company_id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('clicks',      'company_id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('impressions', 'company_id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

\set companies_csv_file :abs_srcdir '/data/companies.csv'
\set campaigns_csv_file :abs_srcdir '/data/campaigns.csv'
\set ads_csv_file :abs_srcdir '/data/ads.csv'
\set clicks_csv_file :abs_srcdir '/data/clicks.csv'
\set impressions_csv_file :abs_srcdir '/data/impressions.csv'
COPY companies from :'companies_csv_file' with csv;
COPY campaigns from :'campaigns_csv_file' with csv;
COPY ads from :'ads_csv_file' with csv;
COPY clicks from :'clicks_csv_file' with csv;
COPY impressions from :'impressions_csv_file' with csv;
SELECT a.campaign_id,
       RANK() OVER (
         PARTITION BY a.campaign_id
         ORDER BY a.campaign_id, count(*) desc
       ), count(*) as n_impressions, a.id
  FROM ads as a
  JOIN impressions as i
    ON i.company_id = a.company_id
   AND i.ad_id      = a.id
 WHERE a.company_id = 5
GROUP BY a.campaign_id, a.id
ORDER BY a.campaign_id, n_impressions desc, a.id
LIMIT 10;
 campaign_id | rank | n_impressions | id
---------------------------------------------------------------------
          34 |    1 |            68 | 264
          34 |    2 |            56 | 266
          34 |    3 |            41 | 267
          34 |    4 |            30 | 265
          34 |    5 |            29 | 268
          34 |    6 |            21 | 263
          35 |    1 |            70 | 270
          35 |    2 |            64 | 269
          35 |    3 |            55 | 276
          35 |    4 |            49 | 275
(10 rows)

DROP TABLE companies, campaigns, ads, clicks, impressions;
-- again with data loaded first
CREATE TABLE companies (
  id bigserial PRIMARY KEY,
  name text NOT NULL,
  image_url text,
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL
);
CREATE TABLE campaigns (
  id bigserial,
  company_id bigint REFERENCES companies (id),
  name text NOT NULL,
  cost_model text NOT NULL,
  state text NOT NULL,
  monthly_budget bigint,
  blacklisted_site_urls text[],
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL,
  PRIMARY KEY (company_id, id)
);
CREATE TABLE ads (
  id bigserial,
  company_id bigint,
  campaign_id bigint,
  name text NOT NULL,
  image_url text,
  target_url text,
  impressions_count bigint DEFAULT 0,
  clicks_count bigint DEFAULT 0,
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL,
  PRIMARY KEY (company_id, id),
  FOREIGN KEY (company_id, campaign_id)
    REFERENCES campaigns (company_id, id)
);
CREATE TABLE clicks (
  id bigserial,
  company_id bigint,
  ad_id bigint,
  clicked_at timestamp without time zone NOT NULL,
  site_url text NOT NULL,
  cost_per_click_usd numeric(20,10),
  user_ip inet NOT NULL,
  user_data jsonb NOT NULL,
  PRIMARY KEY (company_id, id),
  FOREIGN KEY (company_id, ad_id)
    REFERENCES ads (company_id, id)
);
CREATE TABLE impressions (
  id bigserial,
  company_id bigint,
  ad_id bigint,
  seen_at timestamp without time zone NOT NULL,
  site_url text NOT NULL,
  cost_per_impression_usd numeric(20,10),
  user_ip inet NOT NULL,
  user_data jsonb NOT NULL,
  PRIMARY KEY (company_id, id),
  FOREIGN KEY (company_id, ad_id)
    REFERENCES ads (company_id, id)
);
COPY companies from :'companies_csv_file' with csv;
COPY campaigns from :'campaigns_csv_file' with csv;
COPY ads from :'ads_csv_file' with csv;
COPY clicks from :'clicks_csv_file' with csv;
COPY impressions from :'impressions_csv_file' with csv;
SELECT create_distributed_table('companies',   'id');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.companies$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('campaigns',   'company_id');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.campaigns$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('ads',         'company_id');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.ads$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('clicks',      'company_id');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.clicks$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('impressions', 'company_id');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.impressions$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT a.campaign_id,
       RANK() OVER (
         PARTITION BY a.campaign_id
         ORDER BY a.campaign_id, count(*) desc
       ), count(*) as n_impressions, a.id
  FROM ads as a
  JOIN impressions as i
    ON i.company_id = a.company_id
   AND i.ad_id      = a.id
 WHERE a.company_id = 8
GROUP BY a.campaign_id, a.id
ORDER BY a.campaign_id, n_impressions desc, a.id
LIMIT 10;
 campaign_id | rank | n_impressions | id
---------------------------------------------------------------------
          59 |    1 |            70 | 477
          59 |    2 |            69 | 479
          59 |    3 |            63 | 475
          59 |    4 |            52 | 474
          59 |    4 |            52 | 480
          59 |    6 |            32 | 478
          59 |    7 |            29 | 476
          60 |    1 |            70 | 484
          60 |    2 |            68 | 488
          60 |    3 |            67 | 481
(10 rows)

DROP TABLE companies, campaigns, ads, clicks, impressions;
