我有一个postgres数据库,其中包含用户表(userid,firstname,lastname)和usermetadata表(userid,代码,内容,创建日期时间)。我按代码在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中我能想到的最好的方法是加入子选择,这也很慢,我必须为每个代码做一个。

有帮助吗?

解决方案

我想你不愿意修改你的架构,所以我担心我的回答可能没什么帮助,但是这里有......

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

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

这些共同点是有一种确定当前字段集的方法。您只需选择活动用户的所有条目以及NULL“有效期”或“弃用日期”或真正的“有效”。

您可能有兴趣查看有关时态数据库的维基百科条目以及文章时态数据库概念的共识词汇表

其他提示

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

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

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

子选择是执行此类操作的标准方法。您只需要在UserId,代码和日期上使用唯一约束 - 然后您可以运行以下命令:

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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top