【发布时间】:2021-01-20 18:27:49
【问题描述】:
我有一个事件表(id 用作事件 ID),如下所示(另请参阅 SQL fiddle here):
CREATE TABLE ext (
key INT,
id CHAR(1),
pid INT,
sid INT,
oid INT,
event VARCHAR(3)
);
INSERT INTO ext (key, id, pid, sid, oid, event)
VALUES
(1, 'Q', 1, 81, 20, 'tsu'),
(2, 'Q', 1, 81, 9, 'tsu'),
(3, 'Q', 1, 81, 10, 'tsu'),
(4, 'Q', 1, 81, 4, 'tsu'),
(5, 'Q', 1, 81, 15, 'tsu'),
(6, 'Q', 1, 81, 3, 'tsu'),
(7, 'Q', 1, 81, 5, 'tsu'),
(8, 'Q', 1, 81, 18, 'tsu'),
(9, 'Q', 1, 81, 2, 'tsu'),
(10, 'Q', 1, 81, 1, 'tsu'),
(11, 'Q', 1, 81, 7, 'tsu'),
(12, 'f', 2, 2, NULL, 's'),
(13, 'Z', 2, 871, NULL, 'e'),
(14, 'm', 3, 872, 2, 'pof'),
(15, 's', 3, 873, 31, 'pom'),
(16, 'R', 3, 874, 15, 'fc'),
(17, 'R', 3, 874, 1, 'fc'),
(18, 'R', 3, 874, 31, 'fc'),
(19, 'R', 3, 874, 9, 'fc'),
(20, 'R', 3, 874, 10, 'fc'),
(21, 'R', 3, 874, 4, 'fc'),
(22, 'R', 3, 874, 7, 'fc'),
(23, 'R', 3, 874, 3, 'fc'),
(24, 'R', 3, 874, 5, 'fc'),
(25, 'R', 3, 874, 18, 'fc'),
(26, 'R', 3, 874, 20, 'fc'),
(27, 'k', 3, 876, NULL, 's'),
(28, 'a', 3, 950, 31, 'rco'),
(29, 'y', 3, 1285, 7, 'pof'),
(30, 'N', 3, 1286, 22, 'pom'),
(31, 'i', 3, 1299, 1, 'fc'),
(32, 'i', 3, 1299, 5, 'fc'),
(33, 'i', 3, 1299, 3, 'fc'),
(34, 'i', 3, 1299, 20, 'fc'),
(35, 'i', 3, 1299, 4, 'fc'),
(36, 'i', 3, 1299, 9, 'fc'),
(37, 'i', 3, 1299, 10, 'fc'),
(38, 'i', 3, 1299, 22, 'fc'),
(39, 'i', 3, 1299, 15, 'fc'),
(40, 'i', 3, 1299, 18, 'fc'),
(41, 'I', 3, 1407, 9, 'pof'),
(42, 'T', 3, 1408, 19, 'pom'),
(43, 'u', 3, 1575, 4, 'pof'),
(44, 'V', 3, 1576, 30, 'pom'),
(45, 'B', 3, 2019, NULL, 'e'),
(46, 'h', 4, 60, NULL, 'e');
事件根据pid 和sid 列进行排序(例如,您可以分别以天和小时的形式查看它们,因为 pid 的时间单位比 sid 大,因此您应该首先按 pid 和然后通过 sid 获得正确的顺序)。如您所见,一些事件(event = tsu 或event = fc)有不止一行,因为它们引用了许多对象(oid),有些只引用了一个对象(如id = m 的事件),并且有些只有一行,但它们实际上指的是所有先前观察到的不是“死”的物体。它们是一些附加规则:
- 对象在遇到
pof或rco事件时已死亡(如event列中所述) - 当对象遇到
pof事件时,会有另一个对象替换它并标记为pom事件
我需要跟踪当前活动的对象。因此,我想将oid 是NULL 的行与可以从先前事件中推断出的所有活动对象“交叉连接”,其中“交叉连接”是指用oid = NULL 复制该行对于每个当前活跃的oid。
由于可能难以从文本中掌握逻辑,因此我准备了预期的输出(可在SQL fiddle here 获得):
CREATE TABLE intermediate_result (
id CHAR(1),
pid INT,
sid INT,
oid INT,
event VARCHAR(3)
);
INSERT INTO intermediate_result (id, pid, sid, oid, event)
VALUES
('Q', 1, 81, 20, 'tsu'),
('Q', 1, 81, 9, 'tsu'),
('Q', 1, 81, 10, 'tsu'),
('Q', 1, 81, 4, 'tsu'),
('Q', 1, 81, 15, 'tsu'),
('Q', 1, 81, 3, 'tsu'),
('Q', 1, 81, 5, 'tsu'),
('Q', 1, 81, 18, 'tsu'),
('Q', 1, 81, 2, 'tsu'),
('Q', 1, 81, 1, 'tsu'),
('Q', 1, 81, 7, 'tsu'),
('f', 2, 2, 20, 's'),
('f', 2, 2, 9, 's'),
('f', 2, 2, 10, 's'),
('f', 2, 2, 4, 's'),
('f', 2, 2, 15, 's'),
('f', 2, 2, 3, 's'),
('f', 2, 2, 5, 's'),
('f', 2, 2, 18, 's'),
('f', 2, 2, 2, 's'),
('f', 2, 2, 1, 's'),
('f', 2, 2, 7, 's'),
('Z', 2, 871, 20, 'e'),
('Z', 2, 871, 9, 'e'),
('Z', 2, 871, 10, 'e'),
('Z', 2, 871, 4, 'e'),
('Z', 2, 871, 15, 'e'),
('Z', 2, 871, 3, 'e'),
('Z', 2, 871, 5, 'e'),
('Z', 2, 871, 18, 'e'),
('Z', 2, 871, 2, 'e'),
('Z', 2, 871, 1, 'e'),
('Z', 2, 871, 7, 'e'),
('m', 3, 872, 2, 'pof'),
('s', 3, 873, 31, 'pom'),
('R', 3, 874, 15, 'fc'),
('R', 3, 874, 1, 'fc'),
('R', 3, 874, 31, 'fc'),
('R', 3, 874, 9, 'fc'),
('R', 3, 874, 10, 'fc'),
('R', 3, 874, 4, 'fc'),
('R', 3, 874, 7, 'fc'),
('R', 3, 874, 3, 'fc'),
('R', 3, 874, 5, 'fc'),
('R', 3, 874, 18, 'fc'),
('R', 3, 874, 20, 'fc'),
('k', 3, 876, 15, 's'),
('k', 3, 876, 1, 's'),
('k', 3, 876, 31, 's'),
('k', 3, 876, 9, 's'),
('k', 3, 876, 10, 's'),
('k', 3, 876, 4, 's'),
('k', 3, 876, 7, 's'),
('k', 3, 876, 3, 's'),
('k', 3, 876, 5, 's'),
('k', 3, 876, 18, 's'),
('k', 3, 876, 20, 's'),
('a', 3, 950, 31, 'rco'),
('y', 3, 1285, 7, 'pof'),
('N', 3, 1286, 22, 'pom'),
('i', 3, 1299, 1, 'fc'),
('i', 3, 1299, 5, 'fc'),
('i', 3, 1299, 3, 'fc'),
('i', 3, 1299, 20, 'fc'),
('i', 3, 1299, 4, 'fc'),
('i', 3, 1299, 9, 'fc'),
('i', 3, 1299, 10, 'fc'),
('i', 3, 1299, 22, 'fc'),
('i', 3, 1299, 15, 'fc'),
('i', 3, 1299, 18, 'fc'),
('I', 3, 1407, 9, 'pof'),
('T', 3, 1408, 19, 'pom'),
('u', 3, 1575, 4, 'pof'),
('V', 3, 1576, 30, 'pom'),
('B', 3, 2019, 1, 'e'),
('B', 3, 2019, 5, 'e'),
('B', 3, 2019, 3, 'e'),
('B', 3, 2019, 20, 'e'),
('B', 3, 2019, 30, 'e'),
('B', 3, 2019, 19, 'e'),
('B', 3, 2019, 10, 'e'),
('B', 3, 2019, 22, 'e'),
('B', 3, 2019, 15, 'e'),
('B', 3, 2019, 18, 'e'),
('h', 4, 60, 1, 'e'),
('h', 4, 60, 5, 'e'),
('h', 4, 60, 3, 'e'),
('h', 4, 60, 20, 'e'),
('h', 4, 60, 30, 'e'),
('h', 4, 60, 19, 'e'),
('h', 4, 60, 10, 'e'),
('h', 4, 60, 22, 'e'),
('h', 4, 60, 15, 'e'),
('h', 4, 60, 18, 'e');
SQL 版本为 PostgreSQL 9.5。
【问题讨论】:
-
如果您向我们展示表的主键(或候选键)以及列的含义,将会提供信息。
-
该表没有主键,但
id、tid和oid的组合可以形成有效的主键。我无法透露列背后的确切含义,但用抽象的术语来说:该表由许多事件组成(事件ID标记为id,事件类型标记为event)。该事件可以影响许多对象 (oid),但也可以只引用一个对象。pid和sid列的组合记录了事件的时间,因此可以用于排序表。tid实际上是指一组对象,但在示例中它是常量(和冗余) -
没有主键的表没有意义。添加(自然)键。似乎存在一些(及时)排序(否则您将没有事件),因此至少其中一个关键组件应该具有类似时间的角色。并且:如果列对于示例是多余的:将它们排除在外!
-
我不确定您所说的没有主键的表没有意义。。为什么?但为了遵守您的评论,我添加了
key列和后续自然数并删除了备用列。正如我之前提到的,排序是由pid和sid的组合给出的。如果这是来自您,请考虑撤销近距离投票。 -
en.wikipedia.org/wiki/Database_normalization (而您的
key列是 代理键 :它不添加信息,仅添加身份)
标签: sql postgresql time-series postgresql-9.5 gaps-and-islands