在 PostgreSQL 中提供版本化行的好方法是什么?如何查询它们?

发布于 2025-01-05 10:13:48 字数 351 浏览 3 评论 0原文

我想在表中存储不同文本和其他数据的不同版本。对于文本,我的表如下所示:

id BigSerial, PRIMARY KEY  
version Integer  
text Text  
origin BigInt

现在我想在该表中存储不同版本的文本,如下所示:

1,0,"My Text, first Version",null  
2,1,"My Text, second Version",1  
3,0,"My 2nd Text v1",null  
4,1,"My 2nd Text v2",3

我还不知道如何查询每组文本具有最高版本号的行。

I want to store different versions of different texts and other data in a table. For the texts, my table looks like this:

id BigSerial, PRIMARY KEY  
version Integer  
text Text  
origin BigInt

Now I want to store different versions of texts in this table like this:

1,0,"My Text, first Version",null  
2,1,"My Text, second Version",1  
3,0,"My 2nd Text v1",null  
4,1,"My 2nd Text v2",3

I don't know yet how to query for the row with the highest version number for each set of texts.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一城柳絮吹成雪 2025-01-12 10:13:48

Bigserial ID 号没有任何用处。

create temp table my_table (
  id integer not null,
  version integer not null check(version > 0),
  -- Give a lot of thought to whether text should also be unique. *I* think
  -- it probably should, but it's really application-dependent.
  text Text not null unique,
  primary key (id, version)
);

insert into my_table values 
(1, 1, 'My Text, first Version'),
(1, 2, 'My Text, second Version'),
(2, 1, 'My 2nd text v1'),
(2, 2, 'My 2nd text v2')

每个 id 的版本数。

select id, count(*)
from my_table
group by id;

每个 id 的当前版本。

with current_ver as (
  select id, max(version) as version
  from my_table
  group by id
)
select m.* from my_table m
inner join current_ver c on c.id = m.id and c.version = m.version

尽管我使用公用表表达式编写了该内容,但您可能希望创建当前版本的视图。我认为访问此数据的大多数应用程序都需要当前版本。

The Bigserial id number serves no useful purpose.

create temp table my_table (
  id integer not null,
  version integer not null check(version > 0),
  -- Give a lot of thought to whether text should also be unique. *I* think
  -- it probably should, but it's really application-dependent.
  text Text not null unique,
  primary key (id, version)
);

insert into my_table values 
(1, 1, 'My Text, first Version'),
(1, 2, 'My Text, second Version'),
(2, 1, 'My 2nd text v1'),
(2, 2, 'My 2nd text v2')

Number of versions for every id.

select id, count(*)
from my_table
group by id;

Current version for every id.

with current_ver as (
  select id, max(version) as version
  from my_table
  group by id
)
select m.* from my_table m
inner join current_ver c on c.id = m.id and c.version = m.version

Although I wrote that with a common table expression, you probably want to create a view of current versions. I'd think most applications that access this data will need the current version.

酒儿 2025-01-12 10:13:48

时态表扩展可能会有所帮助,如果您不想推出自己的......

https://github.com/arkhipov/temporal_tables

Temporal tables extension might help, if you don't want to roll your own that is...

https://github.com/arkhipov/temporal_tables

书信已泛黄 2025-01-12 10:13:48

由于并非所有文本集都可以以相同的速率获得新版本,因此没有真正的方法可以对版本号进行断言,而无需同时涉及 id 和源。

例如,要知道“5”是特定文本集的最新版本,您必须确定不存在版本“6”。执行此操作的方法是查看版本“6”的行是否具有版本“5”的行的起源。但这只是简化为找到没有其他行声称其为原点的行;你不需要版本号。

因此,您可以将“我是否具有最高版本号”的问题改写为“是否没有其他行以我的 id 作为其起源”。如果没有其他行,那么这是您的最新行,您可以返回结果。您可以使用类似以下查询的方式来完成此操作:

select t.id 
from table parent
left join table descendants on parent.id = descendants.origin 
where descendants.id is null;

生成的连接表中,descendant.id 为 null 的唯一行是最新的行。请注意,父代和子代都是来自同一个表的别名。这就是所谓的“自连接”,当您将分层数据(如版本控制机制)存储在单个表中时,可以很方便地执行此操作。

但值得注意的是,这只会为您找到最新版本。如果您想知道这是哪个版本,那么您肯定会从版本列中受益。否则,您最终将不得不执行递归查询,因为您事先不知道版本列表的深度。没有人喜欢写这些。

希望这有帮助。

Since not all of the set of texts may get new versions at the same rate, there's no real way of making an assertion on version number that won't have to involve both the id and the origin.

For instance, to know that "5" is the latest version of a particular text set, you'll have to establish that there is no version "6". The way to do that is to see if there is a row with a version "6" that has an origin to the row with version "5". But this just reduces to finding a row that has no other row claiming it as an origin point; you don't need the version number.

So, you can rephrase the question of "do I have the highest version number" as "is there no other row that has my id as its origin". If there is no other row, then this is your newest row, and you can return your result. You can accomplish this with something like the following query:

select t.id 
from table parent
left join table descendants on parent.id = descendants.origin 
where descendants.id is null;

The only rows in the resulting joined table where descendant.id will be null are the ones that are the newest. Notice that both parent and descendants are aliased from the same table. This is what is known as a "self-join", and is handy to do when you have hierarchical data (like your versioning mechanism) stored within a single table.

It is worth noting, though, that this only finds the newest version for you. If you want to know which version this is, then you will definitely benefit from having your version column. Otherwise, you will end up having to do a recursive query, since you won't know the depth of your version list up front. No one likes writing those.

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文