PlaytimeHistory/Migrations/001_CreateTables.sql

138 lines
5.7 KiB
SQL

-- All times are UTC. Tables are prefixed pt_ so they can share a database if ever needed.
CREATE TABLE IF NOT EXISTS `pt_servers` (
`id` int NOT NULL,
`address` varchar(64) NOT NULL DEFAULT '',
`hostname` varchar(128) NOT NULL DEFAULT '',
`first_seen` datetime NOT NULL,
`last_seen` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- One row per connection, opened on join and closed on leave or map change.
-- end_kind: 0 open, 1 disconnect, 2 map change, 3 plugin unload, 4 stale (closed at its last
-- heartbeat after the server died).
CREATE TABLE IF NOT EXISTS `pt_sessions` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`session_key` char(32) NOT NULL,
`steamid64` bigint unsigned NOT NULL,
`server_id` int NOT NULL,
`nickname` varchar(128) NOT NULL,
`started_at` datetime NOT NULL,
`ended_at` datetime NULL,
`heartbeat_at` datetime NOT NULL,
`duration_seconds` int unsigned NULL,
`end_kind` tinyint NOT NULL DEFAULT 0,
`connect_map` varchar(64) NOT NULL,
`disconnect_map` varchar(64) NULL,
`disconnect_reason` smallint NULL,
`disconnect_reason_name` varchar(64) NULL,
`players_online` smallint unsigned NOT NULL,
`max_players` smallint unsigned NOT NULL,
`country_iso` char(2) NULL,
`country_name` varchar(64) NULL,
`city` varchar(128) NULL,
`kills` int NULL,
`deaths` int NULL,
`assists` int NULL,
`headshots` int NULL,
`damage` int NULL,
`mvp` int NULL,
`score` int NULL,
`rounds_played` smallint unsigned NULL,
`ping_avg` smallint unsigned NULL,
`ping_min` smallint unsigned NULL,
`ping_max` smallint unsigned NULL,
`ping_samples` int unsigned NULL,
`plugin_version` varchar(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uq_session_key` (`session_key`),
KEY `ix_steamid_started` (`steamid64`, `started_at`),
KEY `ix_server_started` (`server_id`, `started_at`),
KEY `ix_started` (`started_at`),
KEY `ix_server_open` (`server_id`, `ended_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- A stretch of a session where the player's team and alive/dead state didn't change.
-- team: 0 unassigned, 1 spectator, 2 T, 3 CT. alive: NULL when not on T/CT.
CREATE TABLE IF NOT EXISTS `pt_segments` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`segment_key` char(32) NOT NULL,
`session_key` char(32) NOT NULL,
`steamid64` bigint unsigned NOT NULL,
`server_id` int NOT NULL,
`map` varchar(64) NOT NULL,
`team` tinyint NOT NULL,
`alive` tinyint NULL,
`started_at` datetime NOT NULL,
`ended_at` datetime NULL,
`heartbeat_at` datetime NOT NULL,
`seconds` int unsigned NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uq_segment_key` (`segment_key`),
KEY `ix_steamid_started` (`steamid64`, `started_at`),
KEY `ix_started` (`started_at`),
KEY `ix_session` (`session_key`),
KEY `ix_server_open` (`server_id`, `ended_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Running totals, added to in the same transaction that closes a segment or session.
-- spec_seconds covers both spectator and unassigned. total_seconds includes it only when the
-- plugin's CountSpectatorTime is on.
CREATE TABLE IF NOT EXISTS `pt_players` (
`steamid64` bigint unsigned NOT NULL,
`first_seen` datetime NOT NULL,
`last_seen` datetime NOT NULL,
`sessions_count` int unsigned NOT NULL DEFAULT 0,
`total_seconds` bigint unsigned NOT NULL DEFAULT 0,
`t_seconds` bigint unsigned NOT NULL DEFAULT 0,
`ct_seconds` bigint unsigned NOT NULL DEFAULT 0,
`spec_seconds` bigint unsigned NOT NULL DEFAULT 0,
`alive_seconds` bigint unsigned NOT NULL DEFAULT 0,
`dead_seconds` bigint unsigned NOT NULL DEFAULT 0,
`last_nickname` varchar(128) NOT NULL,
`last_country` char(2) NULL,
`last_server_id` int NOT NULL,
PRIMARY KEY (`steamid64`),
KEY `ix_total` (`total_seconds`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `pt_nicknames` (
`steamid64` bigint unsigned NOT NULL,
`nickname` varchar(128) NOT NULL,
`first_seen` datetime NOT NULL,
`last_seen` datetime NOT NULL,
`times_seen` int unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`steamid64`, `nickname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `pt_online_snapshots` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`server_id` int NOT NULL,
`taken_at` datetime NOT NULL,
`players` smallint unsigned NOT NULL,
`bots` smallint unsigned NOT NULL,
`max_players` smallint unsigned NOT NULL,
`map` varchar(64) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_server_taken` (`server_id`, `taken_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Segments split at the hour boundaries: one row per segment per UTC hour it touches. Closed
-- segments only; filter on hour_start (and steamid64) when reading.
CREATE VIEW IF NOT EXISTS `pt_segments_hourly` AS
WITH RECURSIVE h AS (
SELECT s.steamid64, s.server_id, s.map, s.team, s.alive, s.ended_at,
CAST(DATE_FORMAT(s.started_at, '%Y-%m-%d %H:00:00') AS DATETIME) AS hour_start,
s.started_at AS piece_start
FROM pt_segments s
WHERE s.ended_at IS NOT NULL AND s.ended_at > s.started_at
UNION ALL
SELECT steamid64, server_id, map, team, alive, ended_at,
hour_start + INTERVAL 1 HOUR, hour_start + INTERVAL 1 HOUR
FROM h
WHERE hour_start + INTERVAL 1 HOUR < ended_at
)
SELECT steamid64, server_id, map, team, alive, hour_start,
TIMESTAMPDIFF(SECOND, piece_start, LEAST(ended_at, hour_start + INTERVAL 1 HOUR)) AS seconds
FROM h;