此 SQL 的 Cosmos DB 等效项

Posted

技术标签:

【中文标题】此 SQL 的 Cosmos DB 等效项【英文标题】:CosmoDB equivalent of this SQL 【发布时间】:2021-12-26 09:35:21 【问题描述】:

与此等效的好的 cosmodb sql 是什么?我有几乎相同的 sql 在 postgres 中的虚拟表上工作,但似乎无法在 cosmodb 上复制它。

SELECT c.device_id FROM c
    WHERE (c.timestamp, c.device_id)
        IN (
            SELECT c.device_id, MAX(c.timestamp) FROM c WHERE c.device_id in ('00137A100000D2DB', '00137A100000D299') GROUP BY c.device_id
        )

导致错误:

 Gateway Failed to Retrieve Query Plan: Message: "errors":["severity":"Error","location":"start":49,"end":50,"code":"SC1001","message":"Syntax error, incorrect syntax near ','."]
ActivityId: ef246154-4a6b-4657-9cb3-8437a793053e, Microsoft.Azure.Documents.Common/2.14.0, Microsoft.Azure.Documents.Common/2.14.0

示例文档


    "device_id": "00137A100000D299",
    "timestamp": 1602127299000,
    "battery": 3.6,
    "battery_unit": "V",
    "temperature": 0.76,
    "temperature_unit": "°C",
    "humidity": 36.28,
    "humidity_unit": "%",
    "id": "87340b02-2a5d-48db-9dff-97a14785cb7f"

基本上这个想法是获取一些已知设备 ID 的最新时间戳,然后使用它来获取该时间戳的最新数据。

【问题讨论】:

【参考方案1】:

Cosmos DB SQL API 不允许基于子查询或cross document joins 的结果进行任何类型的查找(尽管在 Mongo API 和 Graph API 中可以在文档之间进行查找) - 所以您需要从客户端执行一次查询,然后在第二次查询中使用该值。

或者您可以调整 my answer here 中的 SQL 以在单个聚合查询中完成所有操作。

【讨论】:

你能添加一个例子吗?所以查询应该只获取每个 device_id 的最新行【参考方案2】:

正如@martin-smith 所提到的,除了简单的聚合之外,您不能使用单个查询来实现跨文档魔法。

添加一个更实用的说明,如果您碰巧每个时间戳只有一个数据点,那么您最简单的选择就是对每个设备执行一个简单的有序查询:

SELECT top 1 * FROM c
where c.device_id = @deviceId
order by timestamp desc

通常只发送多个简单且索引良好的查询比尝试通过编写复杂的 SQL 查询来优化那些 10 毫秒的请求到服务器更便宜且更易于维护。

【讨论】:

有没有办法在两个查询中有效地做到这一点?而不是“N”查询,其中“N”是 device_id 的数量?我一直在试验,但似乎不支持 UNION ALL 和其他各种功能,除了使用 max 运算符之外,没有办法在两个查询中有效地做到这一点,这不是我想要的,因为它做了太多的工作。 我不认为只有 2 个查询有任何更简单和/或更好的 RU 使用率。您是否有理由优化查询数量?这个 N 平均有多大?

以上是关于此 SQL 的 Cosmos DB 等效项的主要内容,如果未能解决你的问题,请参考以下文章

此 SQL 查询的 MongoDB 等效项

用于 cosmos db json 中嵌套对象的 Linq

DB2 的 LIMIT 等效项

此 Access 查询的 MS SQL 等效项是啥?

EF 7 中的 db.database.ExecuteSQLCommand 等效项

sql Azure Cosmos DB