将最新的各种usermetadata标签加入用户行

时间:2008-08-24 17:48:13

标签: database postgresql

我有一个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中我能想到的最好的方法是加入子选择,这也很慢,我必须为每个代码做一个。

3 个答案:

答案 0 :(得分: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;

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

答案 1 :(得分:1)

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

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

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

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

您可能有兴趣查看temporal databases上的维基百科条目和文章​​A consensus glossary of temporal database concepts

答案 2 :(得分:0)

子选择是执行此类操作的标准方法。您只需要在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