RDBMS (SQL) 存储带有变量标签/额外列属性的时间序列?
RDBMS (SQL) storing time series with variable labels / extra column attributes?
我想为不同频率(每日、每月、每季度、年度 CY 和年度 FY)的有限大小(大约 6000 系列,50mb 数据)的结构化时间序列数据设置 RDBMS,我想运行 SQL 查询数据库(主要是按时间加入各种 table)。该数据库每月更新一次。此数据库中 table 的变量名称相当技术性,信息量不大。原始数据的标记如下面 table 所示(每月 table 的示例)。
我在 MySQL 开始设置它,并认为只需为 table 配备适当的时间标识符就可以提供我想要的连接功能。但是我不知道如何适当地存储变量标签。是否可以以某种方式向列添加属性?或者我可以 link a table 到 table 映射标签到列名,以便它在连接中携带?或者我应该使用不同类型的数据库进行设置吗? (尽管数据库必须易于设置和托管,并且 SQL 是强烈推荐的)。我很感激任何建议。
更新:
我认为您可以向 MySQL 列和 table 中添加注释,但这些似乎无法以标准方式查询或在连接中携带。是否可以从标准数据库连接器(如 R 语言的连接器:https://github.com/r-dbi/RMySQL)中检索评论中的信息和查询数据?下面是 tables 的 DDL 示例,其中变量标签作为注释。
-- Annual FY Table
CREATE TABLE IF NOT EXISTS BOU_MMI_AF (
FY VARCHAR(7) COMMENT "Fiscal Year (July - June)",
NFA DOUBLE COMMENT "Net Foreign Assets (NFA) (Shs billion)",
NDA DOUBLE COMMENT "Net Domestic Assets (NDA) (Shs billion)",
PRIMARY KEY (FY)
) COMMENT = "Annual FY";
-- Quarterly Table
CREATE TABLE IF NOT EXISTS BOU_FS (
Year INT CHECK (Year >= 1800 AND Year < 2100) COMMENT "Year",
Quarter VARCHAR(2) CHECK (Quarter IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter",
FY VARCHAR(7) COMMENT "Fiscal Year (July - June)",
QFY VARCHAR(2) CHECK (QFY IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter of Fiscal Year",
KA_RC_RWA DOUBLE COMMENT "Capital Adequacy (%): Regulatory capital to risk-weighted assets",
AQ_NPL_GL DOUBLE COMMENT "Asset quality (%): NPLs to total gross loans",
EP_RA DOUBLE COMMENT "Earnings & profitability (%): Return on assets",
L_BFA_TD DOUBLE COMMENT "Liquidity (%): Bank-funded advances to total deposits",
MS_FX_T1CA DOUBLE COMMENT "Market Sensitivity (%): Forex exposure to regulatory tier 1 capital",
PRIMARY KEY (Year, Quarter)
) COMMENT = "Quarterly";
-- Daily Table
CREATE TABLE IF NOT EXISTS BOU_I (
Date DATE CHECK (Date >= '1800-01-01' AND Date < '2100-01-01') COMMENT "Date",
Year INT CHECK (Year >= 1800 AND Year < 2100) COMMENT "Year",
Quarter VARCHAR(2) CHECK (Quarter IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter",
FY VARCHAR(7) COMMENT "Fiscal Year (July - June)",
QFY VARCHAR(2) CHECK (QFY IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter of Fiscal Year",
Month VARCHAR(9) CHECK (Month IN ('January' , 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')) COMMENT "Month",
Day INT CHECK (Day > 0 AND Day < 32) COMMENT "Day",
I_Overnight DOUBLE COMMENT "Daily Interbank Money-Market Rates: Overnight (%)",
I_7day DOUBLE COMMENT "Daily Interbank Money-Market Rates: 7-day (%)",
I_Overall DOUBLE COMMENT "Daily Interbank Money-Market Rates: Overall (%)",
PRIMARY KEY (Date)
) COMMENT = "Daily";
所以如果我执行这样的查询
SELECT * FROM BOU_I NATURAL JOIN BOU_FS NATURAL JOIN BOU_MMI_AF;
使用 R 或 STATA 等统计软件环境,使用 MySQL 连接器连接到数据库,我希望看到一个类似于图中所示的 table,其中我可以检索变量的名称和作为注释存储在 DDL 中的标签。
我会以不同的方式构建您的数据。我会将您所有的度量放在一个 table 中,并且每行有一个度量。然后我会添加一个 DATE table(这样你就有每个度量日期的 week/month/quarter/year 值)和一个 METRIC_TYPE table 来保存每个度量代码的标签。
通过像这样对数据进行规范化,我认为您的设计更加灵活,可以让您随心所欲。
这只是为了说明我的意思 - 它并不是最终的设计:
所以我对@NickW 的建议非常满意。作为参考,我在下面分享了我的最终架构。我对此仍有一些疑问。所以我主要直接查询 DATA table(它有大约 700,000 个 obs),并根据需要加入来自 TIME、SERIES 和 DATASET table 的信息。我注意到检索大量数据可能需要一些时间。所以我想知道:我是否优化了索引?
然后,有一些计算列:DATASOURCE 中的 Ndatasets 列正在计算 DATASET 中按源的 DSID 的数量 table,DATASET 中的更新列显示数据最后一次添加到特定的时间数据集。 DS_From、DS_to 和 S_from、S_to 给出了给定数据集和系列的数据可用的最大时间范围。目前,我正在 R 中进行所有这些计算并插入数据。我想知道是否可以在 MySQL 中完成这些计算,以便拥有自更新列?
感谢您对此的任何进一步评论。
DDL:
DROP SCHEMA IF EXISTS TSDB;
CREATE SCHEMA IF NOT EXISTS TSDB;
USE TSDB;
CREATE TABLE IF NOT EXISTS DATASOURCE (
Source VARCHAR(120),
Source_Url VARCHAR(200),
NDatasets INT NOT NULL,
Desription VARCHAR(3000) NOT NULL,
Access VARCHAR(3000) NOT NULL,
PRIMARY KEY (Source)
);
CREATE TABLE IF NOT EXISTS DATASET (
DSID VARCHAR(30), -- INT
Dataset VARCHAR(120) NOT NULL,
Frequency VARCHAR(9) NOT NULL CHECK (Frequency IN ('Daily' , 'Monthly', 'Quarterly', 'Annual CY', 'Annual FY')),
DS_From DATE CHECK (DS_From >= '1800-01-01' AND DS_From < '2100-01-01'),
DS_To DATE CHECK (DS_To >= '1800-01-01' AND DS_To < '2100-01-01'),
Updated DATE CHECK (Updated >= '1800-01-01' AND Updated < '2100-01-01'),
Desription VARCHAR(3000) NOT NULL,
Source VARCHAR(120), -- NOT NULL
DS_Url VARCHAR(200),
PRIMARY KEY (DSID),
FOREIGN KEY (Source) REFERENCES DATASOURCE (Source) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX idx_dataset_source ON DATASOURCE (Source);
CREATE TABLE IF NOT EXISTS SERIES (
DSID VARCHAR(30), -- INT
Series VARCHAR(30) NOT NULL,
Label VARCHAR(120) NOT NULL,
S_From DATE CHECK (S_From >= '1800-01-01' AND S_From < '2100-01-01'),
S_To DATE CHECK (S_To >= '1800-01-01' AND S_To < '2100-01-01'),
S_Source VARCHAR(120),
S_Url VARCHAR(200),
PRIMARY KEY (DSID, Series),
FOREIGN KEY (DSID) REFERENCES DATASET (DSID) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX idx_series_DSID ON SERIES (DSID);
CREATE TABLE IF NOT EXISTS TIME (
Date DATE UNIQUE CHECK (Date >= '1800-01-01' AND Date < '2100-01-01'),
Year INT NOT NULL CHECK (Year >= 1800 AND Year < 2100),
Quarter INT NOT NULL CHECK (Quarter >= 1 AND Quarter <= 4),
FY CHAR(7) NOT NULL,
QFY INT NOT NULL CHECK (QFY >= 1 AND QFY <= 4),
Month INT NOT NULL CHECK (Month >= 1 AND Month <= 12),
Day INT NOT NULL CHECK (Day > 0 AND Day < 32),
PRIMARY KEY (Date)
);
CREATE TABLE IF NOT EXISTS DATA (
Date DATE,
DSID VARCHAR(30),
Series VARCHAR(30),
Value DOUBLE NOT NULL,
PRIMARY KEY (Date, DSID, Series),
FOREIGN KEY (DSID) REFERENCES DATASET (DSID) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (DSID, Series) REFERENCES SERIES (DSID, Series) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (Date) REFERENCES TIME (Date) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX idx_data_DSID ON DATA (DSID);
CREATE INDEX idx_data_series ON DATA (DSID, Series);
CREATE INDEX idx_data_date ON DATA (Date);
能效比图:
我想为不同频率(每日、每月、每季度、年度 CY 和年度 FY)的有限大小(大约 6000 系列,50mb 数据)的结构化时间序列数据设置 RDBMS,我想运行 SQL 查询数据库(主要是按时间加入各种 table)。该数据库每月更新一次。此数据库中 table 的变量名称相当技术性,信息量不大。原始数据的标记如下面 table 所示(每月 table 的示例)。
我在 MySQL 开始设置它,并认为只需为 table 配备适当的时间标识符就可以提供我想要的连接功能。但是我不知道如何适当地存储变量标签。是否可以以某种方式向列添加属性?或者我可以 link a table 到 table 映射标签到列名,以便它在连接中携带?或者我应该使用不同类型的数据库进行设置吗? (尽管数据库必须易于设置和托管,并且 SQL 是强烈推荐的)。我很感激任何建议。
更新: 我认为您可以向 MySQL 列和 table 中添加注释,但这些似乎无法以标准方式查询或在连接中携带。是否可以从标准数据库连接器(如 R 语言的连接器:https://github.com/r-dbi/RMySQL)中检索评论中的信息和查询数据?下面是 tables 的 DDL 示例,其中变量标签作为注释。
-- Annual FY Table
CREATE TABLE IF NOT EXISTS BOU_MMI_AF (
FY VARCHAR(7) COMMENT "Fiscal Year (July - June)",
NFA DOUBLE COMMENT "Net Foreign Assets (NFA) (Shs billion)",
NDA DOUBLE COMMENT "Net Domestic Assets (NDA) (Shs billion)",
PRIMARY KEY (FY)
) COMMENT = "Annual FY";
-- Quarterly Table
CREATE TABLE IF NOT EXISTS BOU_FS (
Year INT CHECK (Year >= 1800 AND Year < 2100) COMMENT "Year",
Quarter VARCHAR(2) CHECK (Quarter IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter",
FY VARCHAR(7) COMMENT "Fiscal Year (July - June)",
QFY VARCHAR(2) CHECK (QFY IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter of Fiscal Year",
KA_RC_RWA DOUBLE COMMENT "Capital Adequacy (%): Regulatory capital to risk-weighted assets",
AQ_NPL_GL DOUBLE COMMENT "Asset quality (%): NPLs to total gross loans",
EP_RA DOUBLE COMMENT "Earnings & profitability (%): Return on assets",
L_BFA_TD DOUBLE COMMENT "Liquidity (%): Bank-funded advances to total deposits",
MS_FX_T1CA DOUBLE COMMENT "Market Sensitivity (%): Forex exposure to regulatory tier 1 capital",
PRIMARY KEY (Year, Quarter)
) COMMENT = "Quarterly";
-- Daily Table
CREATE TABLE IF NOT EXISTS BOU_I (
Date DATE CHECK (Date >= '1800-01-01' AND Date < '2100-01-01') COMMENT "Date",
Year INT CHECK (Year >= 1800 AND Year < 2100) COMMENT "Year",
Quarter VARCHAR(2) CHECK (Quarter IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter",
FY VARCHAR(7) COMMENT "Fiscal Year (July - June)",
QFY VARCHAR(2) CHECK (QFY IN ('Q1', 'Q2', 'Q3', 'Q4')) COMMENT "Quarter of Fiscal Year",
Month VARCHAR(9) CHECK (Month IN ('January' , 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')) COMMENT "Month",
Day INT CHECK (Day > 0 AND Day < 32) COMMENT "Day",
I_Overnight DOUBLE COMMENT "Daily Interbank Money-Market Rates: Overnight (%)",
I_7day DOUBLE COMMENT "Daily Interbank Money-Market Rates: 7-day (%)",
I_Overall DOUBLE COMMENT "Daily Interbank Money-Market Rates: Overall (%)",
PRIMARY KEY (Date)
) COMMENT = "Daily";
所以如果我执行这样的查询
SELECT * FROM BOU_I NATURAL JOIN BOU_FS NATURAL JOIN BOU_MMI_AF;
使用 R 或 STATA 等统计软件环境,使用 MySQL 连接器连接到数据库,我希望看到一个类似于图中所示的 table,其中我可以检索变量的名称和作为注释存储在 DDL 中的标签。
我会以不同的方式构建您的数据。我会将您所有的度量放在一个 table 中,并且每行有一个度量。然后我会添加一个 DATE table(这样你就有每个度量日期的 week/month/quarter/year 值)和一个 METRIC_TYPE table 来保存每个度量代码的标签。
通过像这样对数据进行规范化,我认为您的设计更加灵活,可以让您随心所欲。
这只是为了说明我的意思 - 它并不是最终的设计:
所以我对@NickW 的建议非常满意。作为参考,我在下面分享了我的最终架构。我对此仍有一些疑问。所以我主要直接查询 DATA table(它有大约 700,000 个 obs),并根据需要加入来自 TIME、SERIES 和 DATASET table 的信息。我注意到检索大量数据可能需要一些时间。所以我想知道:我是否优化了索引?
然后,有一些计算列:DATASOURCE 中的 Ndatasets 列正在计算 DATASET 中按源的 DSID 的数量 table,DATASET 中的更新列显示数据最后一次添加到特定的时间数据集。 DS_From、DS_to 和 S_from、S_to 给出了给定数据集和系列的数据可用的最大时间范围。目前,我正在 R 中进行所有这些计算并插入数据。我想知道是否可以在 MySQL 中完成这些计算,以便拥有自更新列?
感谢您对此的任何进一步评论。
DDL:
DROP SCHEMA IF EXISTS TSDB;
CREATE SCHEMA IF NOT EXISTS TSDB;
USE TSDB;
CREATE TABLE IF NOT EXISTS DATASOURCE (
Source VARCHAR(120),
Source_Url VARCHAR(200),
NDatasets INT NOT NULL,
Desription VARCHAR(3000) NOT NULL,
Access VARCHAR(3000) NOT NULL,
PRIMARY KEY (Source)
);
CREATE TABLE IF NOT EXISTS DATASET (
DSID VARCHAR(30), -- INT
Dataset VARCHAR(120) NOT NULL,
Frequency VARCHAR(9) NOT NULL CHECK (Frequency IN ('Daily' , 'Monthly', 'Quarterly', 'Annual CY', 'Annual FY')),
DS_From DATE CHECK (DS_From >= '1800-01-01' AND DS_From < '2100-01-01'),
DS_To DATE CHECK (DS_To >= '1800-01-01' AND DS_To < '2100-01-01'),
Updated DATE CHECK (Updated >= '1800-01-01' AND Updated < '2100-01-01'),
Desription VARCHAR(3000) NOT NULL,
Source VARCHAR(120), -- NOT NULL
DS_Url VARCHAR(200),
PRIMARY KEY (DSID),
FOREIGN KEY (Source) REFERENCES DATASOURCE (Source) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX idx_dataset_source ON DATASOURCE (Source);
CREATE TABLE IF NOT EXISTS SERIES (
DSID VARCHAR(30), -- INT
Series VARCHAR(30) NOT NULL,
Label VARCHAR(120) NOT NULL,
S_From DATE CHECK (S_From >= '1800-01-01' AND S_From < '2100-01-01'),
S_To DATE CHECK (S_To >= '1800-01-01' AND S_To < '2100-01-01'),
S_Source VARCHAR(120),
S_Url VARCHAR(200),
PRIMARY KEY (DSID, Series),
FOREIGN KEY (DSID) REFERENCES DATASET (DSID) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX idx_series_DSID ON SERIES (DSID);
CREATE TABLE IF NOT EXISTS TIME (
Date DATE UNIQUE CHECK (Date >= '1800-01-01' AND Date < '2100-01-01'),
Year INT NOT NULL CHECK (Year >= 1800 AND Year < 2100),
Quarter INT NOT NULL CHECK (Quarter >= 1 AND Quarter <= 4),
FY CHAR(7) NOT NULL,
QFY INT NOT NULL CHECK (QFY >= 1 AND QFY <= 4),
Month INT NOT NULL CHECK (Month >= 1 AND Month <= 12),
Day INT NOT NULL CHECK (Day > 0 AND Day < 32),
PRIMARY KEY (Date)
);
CREATE TABLE IF NOT EXISTS DATA (
Date DATE,
DSID VARCHAR(30),
Series VARCHAR(30),
Value DOUBLE NOT NULL,
PRIMARY KEY (Date, DSID, Series),
FOREIGN KEY (DSID) REFERENCES DATASET (DSID) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (DSID, Series) REFERENCES SERIES (DSID, Series) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (Date) REFERENCES TIME (Date) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX idx_data_DSID ON DATA (DSID);
CREATE INDEX idx_data_series ON DATA (DSID, Series);
CREATE INDEX idx_data_date ON DATA (Date);
能效比图: