Sql 棘手的Rails 5 ActiveRecord“;其中;查询涉及多个关联模型和一个;或;操作人员
我有一个PurchaseOrder模型,它与商品模型有很多关系。PurchaseOrder和行项目模型都与交付模型有很多关系。交付模型具有“预期到达”属性。我需要获取符合以下任一条件的所有采购订单: a) 订单的交货具有“预期到货”属性,即昨天或更早 b) 订单的任何行项目都具有“预期到货”属性为“昨天”或“更早”的交货 我曾计划使用Rails 5Sql 棘手的Rails 5 ActiveRecord“;其中;查询涉及多个关联模型和一个;或;操作人员,sql,ruby-on-rails,activerecord,ruby-on-rails-5,Sql,Ruby On Rails,Activerecord,Ruby On Rails 5,我有一个PurchaseOrder模型,它与商品模型有很多关系。PurchaseOrder和行项目模型都与交付模型有很多关系。交付模型具有“预期到达”属性。我需要获取符合以下任一条件的所有采购订单: a) 订单的交货具有“预期到货”属性,即昨天或更早 b) 订单的任何行项目都具有“预期到货”属性为“昨天”或“更早”的交货 我曾计划使用Rails 5或操作符,但显然,当将或与连接或包含组合时,Rails中存在一个已知错误: 然后我尝试使用组和拥有,如下所示: PurchaseOrder.left
或
操作符,但显然,当将或
与连接
或包含
组合时,Rails中存在一个已知错误:
然后我尝试使用组
和拥有
,如下所示:
PurchaseOrder.left_joins(:deliveries, {line_items: :deliveries})
.group("purchase_orders.id")
.having("MAX(line_items.deliveries.expected_arrival) <= ?
OR MAX(deliveries.expected_arrival) <= ?",
Time.now,
Time.now)`
第1行:…“是采购订单的空组。id具有(最大值)(第\u行项目。。。
^
提示:表“deliveries”有一个条目,但不能从查询的这一部分引用它。
`
奇怪的是,Rails告诉我,我不能以这种方式访问deliveries表,因为以下每个查询都是自己工作的:
PurchaseOrder.left_joins(:deliveries).group("purchase_orders.id").having("MAX(deliveries.expected_arrival) <= ?", Time.now)`
PurchaseOrder.left_joins({line_items: :deliveries}).group("purchase_orders.id").having("MAX(deliveries.expected_arrival) <= ?", Time.now)`
PurchaseOrder.left_joins(:deliveries.group)(“purchaseu orders.id”).having(“MAX(deliveries.expected_arrival)据我所知,Rails没有能够对同一个表进行多个连接的内置连接方法,但sql有。从我们可以看出,可以通过向joins语句添加一个参数来命名连接
SELECT i.name as name, v1.value as value_1, v2.value as value_2
FROM item i
INNER JOIN item_value iv ON iv.item = i.id
INNER JOIN property p ON iv.property = p.id
LEFT JOIN value v1 ON p.name = 'prop1' AND v1.id = iv.value
LEFT JOIn value v2 ON p.name = 'prop2' AND v2.id = iv.value
Rails允许您将sql作为JOIN语句的一部分,如中所示
对于这个用例
PurchaseOrder
.joins("LEFT JOIN deliveries_purchase_orders on purchase_orders.id = deliveries_purchase_orders.purchase_order_id)
.joins("LEFT JOIN deliveries order_deliveries ON deliveries.id = deliveries_purchase_orders.delivery_id")
.left_joins(:line_items)
.joins("LEFT JOIN deliveries_line_items on line_items.id = deliveries_line_items.line_item_id)
.joins("LEFT JOIN deliveries item_deliveries ON deliveries.id = deliveries_line_items.delivery_id")
.group("purchase_orders.id")
.having("MAX(item_deliveries.expected_arrival) <= ?
OR MAX(order_deliveries.expected_arrival) <= ?",
Time.now,
Time.now)`
PurchaseOrder
.joins(“左连接交货\采购订单上的采购订单。id=交货\采购订单。采购订单\ id”)
.joins(“左连接交货订单\交货时交货。id=交货\采购订单。交货\ id”)
.左\u联接(:行\u项)
.joins(“左连接交货\u行\u行项目上的项目。id=交货\u行项目。行项目\u id”)
.joins(“左连接交付项目\交付上的交付。id=交付\行\项目。交付\ id”)
.group(“采购订单.id”)
.拥有(“最大(物品交付量。预计到达量)试试看
PurchaseOrder.includes(:deliveries, line_items: :deliveries)
.group("purchase_orders.id")
.where("MAX(line_items.deliveries.expected_arrival) <= ?
OR MAX(deliveries.expected_arrival) <= ?",
Time.now,
Time.now)
PurchaseOrder.包括(:交货,行项目::交货)
.group(“采购订单.id”)
.where(“MAX(line\u items.deliveries.expected\u arrival)想要帮助我更喜欢Rails命令而不是香草SQL。Delivery
模型是否与PurchaseOrder
/line item
有多态关联,或者每个都有外键?@MichaelGorman存在多对多关系(即联接表)在交付和采购订单之间,以及交付和行项目之间。这使它变得有点棘手,但仍然可行。我将更新我的答案,以反映这不正是我在最初问题中发布的内容吗?唯一的区别似乎是包含与左连接。是否AS
语句有意还是无意?我尝试了您的确切代码(顺便说一句,缺少了一些结束引号)和以下()代码,但不断出现如下错误:ActiveRecord::StatementInvalid:PG::UndefinedTable:ERROR:deliveries\u purchase\u orders表的子句条目中缺少第1行:…ries AS order\u deliveries ON order\u deliveries.id=deliveries…
看起来可能只是连接表的名称不是deliveries\u purchase\u orders
。连接表的名称是什么?看起来连接表的名称是问题的一部分。我得到了下面的语句,它可以工作:PurchaseOrder.JOIN(“左连接交货\采购\订单上的订单。id=交货\采购\订单。采购\订单\ id”).JOIN(“左连接交货作为订单\订单上的交货\交货。id=交货\采购\订单。交货\ id”)。左连接(:行\项目)
,但在连接以下内容时失败:(“LEFT JOIN delivery\u line\u items on line\u items.id=delivery\u line\u items.line\u items\u id”)
错误为:ActiveRecord::StatementInvalid:PG::UndefinedTable:错误:表“line\u items”的子句条目中缺少“第1行:…ders.delivery\u id LEFT JOIN delivery\u LINE\u items on LINE\u items…^
(注意,向上箭头指向末尾的LINE\u items
)。我猜问题是由LEFT\u JOIN(:LINE\u items)引起的
。您能看到在这种情况下生成的完整sql吗?
PurchaseOrder.includes(:deliveries, line_items: :deliveries)
.group("purchase_orders.id")
.where("MAX(line_items.deliveries.expected_arrival) <= ?
OR MAX(deliveries.expected_arrival) <= ?",
Time.now,
Time.now)