4

我有一个带有用户表(用户 ID、名字、姓氏)和用户元数据表(用户 ID、代码、内容、创建日期时间)的 postgres 数据库。我通过代码将有关每个用户的各种信息存储在 usermetadata 表中,并保留完整的历史记录。例如,用户(用户 ID 15)具有以下元数据:

15, 'QHS', '20', '2008-08-24 13:36:33.465567-04'  
15, 'QHE', '8', '2008-08-24 12:07:08.660519-04'  
15, 'QHS', '21', '2008-08-24 09:44:44.39354-04'  
15, 'QHE', '10', '2008-08-24 08:47:57.672058-04'  

我需要获取所有用户的列表以及每个用户元数据代码的最新值。我以编程方式完成了这项工作,当然速度非常慢。在 SQL 中我能想到的最好的方法是加入子选择,这也很慢,我必须为每个代码做一个。

4

3 回答 3

6

这实际上在 PostgreSQL 中并不难做到,因为它的 SELECT 语法中有“DISTINCT ON”子句(DISTINCT ON 不是标准 SQL)。

SELECT DISTINCT ON (code) code, content, createtime
FROM metatable
WHERE userid = 15
ORDER BY code, createtime DESC;

这会将返回的结果限制为每个唯一代码的第一个结果,如果您按创建时间降序对结果进行排序,您将获得每个结果中的最新结果。

于 2008-08-26T00:29:36.100 回答
1

我想您不愿意修改您的架构,所以恐怕我的回答可能没有太大帮助,但是这里......

一种可能的解决方案是在您插入“弃用日期”时将时间字段留空,直到它被更新的值替换。另一种方法是使用“活动”列扩展表,但这会引入一些冗余。

经典的解决方案是同时设置“Valid-From”和“Valid-To”字段,其中“Valid-To”字段为空白,直到其他条目变为有效。这可以通过使用触发器或类似方法轻松处理。使用约束来确保每种类型中只有一个有效项将确保数据完整性。

这些的共同点是有一种确定当前字段集的方法。您只需选择具有活动用户和 NULL 'Valid-To' 或 'deprecation date' 或真正的 'active' 的所有条目。

您可能有兴趣查看有关时间数据库的 Wikipedia 条目和文章​​时间数据库概念的共识词汇表

于 2008-08-24T18:11:02.603 回答
0

子选择是做这种事情的标准方法。您只需要对 UserId、Code 和 Date 设置唯一约束 - 然后您可以运行以下命令:

SELECT * 
FROM Table
JOIN (
   SELECT UserId, Code, MAX(Date) as LastDate
   FROM Table
   GROUP BY UserId, Code
) as Latest ON
   Table.UserId = Latest.UserId
   AND Table.Code = Latest.Code
   AND Table.Date = Latest.Date
WHERE
   UserId = @userId
于 2008-08-27T14:42:34.247 回答