在保留 link-table 历史记录的数据库模式中,什么是好的做法?
What is good practice in a DB schema keeping a history of a link-table?
事不宜迟举个例子:
让我们考虑一个任意的例子,3 tables,一个有工人,一个有任务,一个 link table 并考虑历史的分辨率 'days'
Table "workers", (PK)id
id | name
---+-----------
1 | Frank
2 | Sam
3 | Tony
---+-----------
Table "tasks", (PK)id
id | name
---+--------------------
1 | walking the dog
2 | feeding the cat
3 | charging the robot
---+--------------------
Table"task_assignments",
(PK)workers.id as w_id, (FK)w_id, (FK) tasks.id as t_id
w_id | t_id
-----+------
1 | 2
2 | 3
3 | 2
-----+------
所以现在一切似乎都很清楚,在这个例子中,t_id 是 (PK) 的一部分可能也没有意义。 link table 很简单,但我如何实现良好的历史记录?
假设:
- 我于 1970 年 1 月 1 日将 w_id(1) 分配给 t_id(2)。
- 1970 年 1 月 2 日,我取消了 w_id(1) 的任务,没有留下任何条目
link table.
- 在 1970 年 1 月 8 日,我将 w_id(1) 分配给 t_id(1),这需要更长的时间。
- 1970 年 1 月 15 日,我再次将 w_id(1) 从他的任务中取消分配,没有留下
link table.
中的条目
如何正确实现此历史记录以实现数据一致性和便于查询?
我想轻松查询:
- w_id(?) 在 1970-01-03 做什么任务?
- 哪些 w_id 从 1970-01-01 到 1970-01-10 没有任务?
- 从 1970-01-10 到 1970-01-12,w_id(?) 在做什么任务?
- 哪些任务目前没有分配给任何工作人员?
我可以更改 link-table 以包含日期戳作为 (PK) 的一部分并以这种方式存储分配并简单地使用 t_id 存储一个新行=null 像这样取消分配?
date_set | w_id | t_id
------------+------+------
1970-01-01 | 1 | 2
1970-01-02 | 2 | 3
1970-01-01 | 3 | 2
1970-01-02 | 1 | null
------------+------+------
或者我是否制作某种 "history-table" 但是在不加倍 link-table 的情况下放什么?为 link table 创建一个 AI-PK 并将其存储在带有日期戳的历史记录 table 中的一行中?以及如何处理未分配的周期?
是否有某种 "schema design patter" 用于此?我根本不知道要搜索什么,所以基本上接受table 的答案也会是对涵盖该主题的文章的 link。
您可以使用 table assignments 如下所示:
date_start | date_finish | w_id | t_id
------------+-------------+------+-----
1970-01-01 | 1970-01-02 | 1 | 2
1970-01-01 | 1970-01-02 | 3 | 2
1970-01-02 | null | 1 | 2
1970-01-02 | null | 1 | 3
------------+-------------+------+------
使用此代码添加一些测试数据:
CREATE table workers (
id int,
name text,
primary key (id)
);
CREATE table tasks (
id int,
name text,
primary key (id)
);
CREATE table assignments (
w_id int,
t_id int,
date_start date,
date_finish date
);
INSERT INTO workers VALUES (1, 'worker_a'), (2, 'worker_b'), (3, 'worker_c');
INSERT INTO tasks VALUES (1, 'task_1'), (2, 'task_2'), (3, 'task_3');
INSERT INTO assignments VALUES (1, 2, '1970-01-01', '1970-01-02'), (3, 2, '1970-01-01', '1970-01-02'), (1, 2, '1970-01-03', NULL), (1, 3, '1970-01-02', NULL);
现在我们可以试验所需的查询。
w_id(1) 在 1970-01-03 做什么任务?
SELECT t_id FROM assignments WHERE w_id = 1 AND '1970-01-03' BETWEEN date_start AND date_finish;
+------+
| t_id |
+------+
| 2 |
+------+
哪些 w_id 从 1970-01-01 到 1970-01-10 没有任务?
SELECT distinct id FROM workers WHERE id NOT IN (SELECT w_id FROM assignments WHERE ( (date_start <= '1970-01-01' AND date_finish IS NULL) OR (date_start <= '1970-01-01' AND date_finish >= '1970-01-01') OR (date_start >= '1970-01-01' AND date_start <= '1970-01-10')));
+----+
| id |
+----+
| 2 |
+----+
从 1970-01-03 到 1970-01-12,w_id(1) 在做什么任务?
SELECT t_id FROM assignments WHERE w_id = 1 AND ( (date_start >= 1970-01-03 AND date_finish IS NULL) OR (date_start >= 1970-01-03 AND date_finish <= 1970-01-12));
+------+
| t_id |
+------+
| 2 |
| 3 |
+------+
哪些任务目前没有分配给任何工作人员? (假设今天是 1970-02-01)
SELECT distinct id FROM tasks WHERE id NOT IN (SELECT t_id FROM assignments WHERE ( (date_start <= '1970-02-01' AND date_finish IS NULL) OR (date_start <= '1970-02-01' AND date_finish >= '1970-02-01') OR (date_start >= '1970-02-01' AND date_start <= '1970-02-01')));
+----+
| id |
+----+
| 1 |
+----+
事不宜迟举个例子:
让我们考虑一个任意的例子,3 tables,一个有工人,一个有任务,一个 link table 并考虑历史的分辨率 'days'
Table "workers", (PK)id
id | name
---+-----------
1 | Frank
2 | Sam
3 | Tony
---+-----------
Table "tasks", (PK)id
id | name
---+--------------------
1 | walking the dog
2 | feeding the cat
3 | charging the robot
---+--------------------
Table"task_assignments", (PK)workers.id as w_id, (FK)w_id, (FK) tasks.id as t_id
w_id | t_id
-----+------
1 | 2
2 | 3
3 | 2
-----+------
所以现在一切似乎都很清楚,在这个例子中,t_id 是 (PK) 的一部分可能也没有意义。 link table 很简单,但我如何实现良好的历史记录?
假设:
- 我于 1970 年 1 月 1 日将 w_id(1) 分配给 t_id(2)。
- 1970 年 1 月 2 日,我取消了 w_id(1) 的任务,没有留下任何条目 link table.
- 在 1970 年 1 月 8 日,我将 w_id(1) 分配给 t_id(1),这需要更长的时间。
- 1970 年 1 月 15 日,我再次将 w_id(1) 从他的任务中取消分配,没有留下 link table. 中的条目
如何正确实现此历史记录以实现数据一致性和便于查询?
我想轻松查询:
- w_id(?) 在 1970-01-03 做什么任务?
- 哪些 w_id 从 1970-01-01 到 1970-01-10 没有任务?
- 从 1970-01-10 到 1970-01-12,w_id(?) 在做什么任务?
- 哪些任务目前没有分配给任何工作人员?
我可以更改 link-table 以包含日期戳作为 (PK) 的一部分并以这种方式存储分配并简单地使用 t_id 存储一个新行=null 像这样取消分配?
date_set | w_id | t_id
------------+------+------
1970-01-01 | 1 | 2
1970-01-02 | 2 | 3
1970-01-01 | 3 | 2
1970-01-02 | 1 | null
------------+------+------
或者我是否制作某种 "history-table" 但是在不加倍 link-table 的情况下放什么?为 link table 创建一个 AI-PK 并将其存储在带有日期戳的历史记录 table 中的一行中?以及如何处理未分配的周期?
是否有某种 "schema design patter" 用于此?我根本不知道要搜索什么,所以基本上接受table 的答案也会是对涵盖该主题的文章的 link。
您可以使用 table assignments 如下所示:
date_start | date_finish | w_id | t_id
------------+-------------+------+-----
1970-01-01 | 1970-01-02 | 1 | 2
1970-01-01 | 1970-01-02 | 3 | 2
1970-01-02 | null | 1 | 2
1970-01-02 | null | 1 | 3
------------+-------------+------+------
使用此代码添加一些测试数据:
CREATE table workers (
id int,
name text,
primary key (id)
);
CREATE table tasks (
id int,
name text,
primary key (id)
);
CREATE table assignments (
w_id int,
t_id int,
date_start date,
date_finish date
);
INSERT INTO workers VALUES (1, 'worker_a'), (2, 'worker_b'), (3, 'worker_c');
INSERT INTO tasks VALUES (1, 'task_1'), (2, 'task_2'), (3, 'task_3');
INSERT INTO assignments VALUES (1, 2, '1970-01-01', '1970-01-02'), (3, 2, '1970-01-01', '1970-01-02'), (1, 2, '1970-01-03', NULL), (1, 3, '1970-01-02', NULL);
现在我们可以试验所需的查询。
w_id(1) 在 1970-01-03 做什么任务?
SELECT t_id FROM assignments WHERE w_id = 1 AND '1970-01-03' BETWEEN date_start AND date_finish;
+------+
| t_id |
+------+
| 2 |
+------+
哪些 w_id 从 1970-01-01 到 1970-01-10 没有任务?
SELECT distinct id FROM workers WHERE id NOT IN (SELECT w_id FROM assignments WHERE ( (date_start <= '1970-01-01' AND date_finish IS NULL) OR (date_start <= '1970-01-01' AND date_finish >= '1970-01-01') OR (date_start >= '1970-01-01' AND date_start <= '1970-01-10')));
+----+
| id |
+----+
| 2 |
+----+
从 1970-01-03 到 1970-01-12,w_id(1) 在做什么任务?
SELECT t_id FROM assignments WHERE w_id = 1 AND ( (date_start >= 1970-01-03 AND date_finish IS NULL) OR (date_start >= 1970-01-03 AND date_finish <= 1970-01-12));
+------+
| t_id |
+------+
| 2 |
| 3 |
+------+
哪些任务目前没有分配给任何工作人员? (假设今天是 1970-02-01)
SELECT distinct id FROM tasks WHERE id NOT IN (SELECT t_id FROM assignments WHERE ( (date_start <= '1970-02-01' AND date_finish IS NULL) OR (date_start <= '1970-02-01' AND date_finish >= '1970-02-01') OR (date_start >= '1970-02-01' AND date_start <= '1970-02-01')));
+----+
| id |
+----+
| 1 |
+----+