我正在尝试编写一个 OData URL,它将从具有一对多关系的相关集合上的过滤器的集合中进行选择。过滤器要求相关的集合项都具有某些属性的特定值。
为了说明这个问题,我为 Northwind 示例 OData 服务编写了一个类似的 URL。此查询应选择所有订单已由同一员工处理的所有客户。 http://services.odata.org/V3/Northwind/Northwind.svc/Customers?$expand=Orders&$filter=Orders/all(o: o/EmployeeID eq 4)&$select=CustomerID,Orders/OrderID,Orders /员工ID
这给出了:
{"odata.metadata":"http://services.odata.org/V3/Northwind/Northwind.svc/$metadata#Customers&$select=CustomerID,Orders/OrderID,Orders/EmployeeID","value":
[{"Orders":[{"OrderID":10259,"EmployeeID":4}],"CustomerID":"CENTC"}
,{"Orders":[],"CustomerID":"FISSA"}
,{"Orders":[],"CustomerID":"PARIS"}]}
第一个项目确实包含员工 4 处理的所有(在这种情况下,只有一个)订单。对于第二个和第三个,结果集中没有订单项目。进一步检查,http://services.odata.org/V3/Northwind/Northwind.svc/Customers?$expand=Orders&$filter=(CustomerID eq 'FISSA')&$select=CustomerID,Orders/OrderID,Orders/ EmployeeID显示“FISSA”确实没有任何订单(“PARIS”也是如此)。
也许有人可以推断,因为“FISSA”没有任何命令违反过滤谓词,所以谓词成立。事实上,这可能是这个查询在 SQL 中解析的方式:
select c.CustomerID
from Customers c
where c.CustomerID not in (select CustomerID from Orders o where o.EmployeeID != 4)
返回相同的 3 个客户,但加入 Orders 表可以解决这个问题:
select c.CustomerID, o.OrderID, o.EmployeeID
from Customers c
join Orders o
on c.CustomerID = o.CustomerID
where c.CustomerID not in (select CustomerID from Orders o where o.EmployeeID != 4)
只返回“CENTC”。
我认为“FISSA”的过滤谓词未确定,并且按照三值逻辑规则,“FISSA”和“PARIS”不应该出现在结果集中。所以,我认为这是这个 OData 实现中的一个错误。
有人知道正确的 OData 请求查询以排除没有订单的客户吗?