我需要找到每个人最后一次登录的记录。这适用于T-SQL
SELECT *
FROM
(
SELECT lh.*, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY DateCreated DESC) AS RowNumber
FROM LoginHistory lh
) lhp
where lhp.RowNumber = 1
但是由于DocumentDb减少feature set,我无法弄清楚如何处理这个问题。
我认为这需要作为存储过程来解决,但我无法想象如何构建它。循环多个异步调用? (不确定如何做到这一点。)下载所有记录并使用JS过滤它们?
我该如何翻译?
更新:示例输出
PARTITION BY类似于GROUP BY,但它不是聚合结果,而是将记录视为一种范围。所以
SELECT lh.*, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY DateCreated DESC) AS RowNumber
FROM LoginHistory lh
会返回类似
的内容UserId DateCreated RowNumber
1 2015-12-10 22:44:03 1
1 2015-12-10 13:35:12 2
1 2015-12-09 18:52:25 3
2 2015-12-10 20:53:13 1
2 2015-12-10 08:12:41 2
它基本上说,“对于给定的UserId,按DateCreated命令这些记录。”
然后我只在外部查询中选择RowNumber = 1,我有每个用户的最新记录。
我的问题使用了SQL 2015+语法,但也可以使用pre-SQL 2005语法,这可以通过类似this的方式完成:
Select Date, User, Status, Notes
from [SOMETABLE]
inner join
(
Select max(Date) as LatestDate, [User]
from [SOMETABLE]
Group by User
) SubMax
on [SOMETABLE].Date = SubMax.LatestDate
and [SOMETABLE].User = SubMax.User
不幸的是,DocumentDb也不支持GroupBy。
答案 0 :(得分:1)
看起来您想要给定UserId的最新值。我可以想到三种替代方法,你建议第二种:
将所有内容提取回客户端并提取您想要的行。可能是带宽占用并且存在延迟问题,具体取决于数据的大小。
编写存储过程。如果这是一项您想要做很多事情并且性能至关重要的操作,那么您可能希望采用这种方法。我能够快速调整我的countDocuments sproc来创建你想要的sproc。您可以找到它here(更新:已添加tests并修复了我第一次发布时的错误)。如果您使用的是.NET,则需要预编译该sproc(用CoffeeScript编写)并将其发送到您的服务器。如果你在node.js上,我建议使用documentdb-utils.loadSprocs来加载特定目录中的所有sprocs。 loadSprocs负责编译,甚至允许您通过实现require()
支持来模块化和使用您的sprocs中的npm包。
如果您希望进行其他聚合或分区,那么我建议使用更通用的解决方案documentdb-lumenize,它是在DocumentDB中的存储过程中运行的聚合“库”。使用配置调用存储过程以指定要执行的“聚合”(或分区)。本答案的其余部分是关于如何使用documentdb-lumenize执行此操作的说明。
firstValue(如果您使用ORDER BY DESC)或lastValue(如果您使用默认ASC)聚合函数是您想要的。
假设你使用的是node.js / CoffeeScript,我会给出答案,但你可以使用JavaScript和/或.NET。无论你喜欢什么,我都可以为你做一个完整的例子。请告诉我。
第一步是您的查询:
filterQuery = "SELECT c.ValueToReturn FROM c ORDER BY c.DateCreated"
接下来,您将定义您希望“分区”
的字段dimensions = [{field: "UserId"}]
然后,您需要定义“指标”。
metrics = [{field: 'ValueToReturn', f: "lastValue", as: "Last Value"}]
最后,将所有内容捆绑到配置对象
中cubeConfig = {dimensions, metrics}
config = {cubeConfig, filterQuery}
然后,在调用“cube”存储过程时,将config作为唯一参数发送。有关如何将多维数据集添加到集合并执行它的示例,请参阅documentdb-lumenize docs(提供了CoffeeScript / JavaScript / .NET示例)。
我有一个基于浏览器的Lumenize实现,它允许我给你一个JSFiddle working example。唯一的区别是我没有为浏览器配置指定filterQuery。由于documentdb-lumenize在DocumentDB中工作,因此需要这些基于浏览器不需要的额外信息。它与上面的示例略有不同,因为我坚持使用我刚剪切和粘贴的示例数据中的DESC排序顺序。你想要的那个是“firstValue”。如果排序顺序是ASC,那么你需要“lastValue”,这就是我在上面显示的内容。
注意,上面的例子只返回一个字段(此处显示为“ValueToReturn”。如果你想要更多,你需要确保它们在你的SELECT子句中(或者只是说“*”)您需要为指标表中的每个字段添加一行。您可以通过编程方式构建指标表,即使您需要50个字段,也只需要几行代码。如果您需要CoffeeScript / JavaScript,请告诉我们。如何以编程方式执行此操作的示例。