[英]Problems with SQL, Arel and filtering out records. Rails. Could use some advice
我對SQL和Arel很爛。 我什至不知道什么是Arel或如何使用它。 是否有很好的資源?
我有一個問題,我不知道為什么花了我這么長時間。 也許人們可以指出為什么這需要我這么長時間。
無論如何,我有一個Products
表和一個Restrictions
表。 產品可能有很多限制。 限制是美國的州。 我的大多數產品都沒有限制,但是我的其中一款產品有限制(由於“ CT”具有瘋狂的法律,因此無法在“ CT”中出售)。
我想退回所有CT不受限制的產品。 但是,此查詢不起作用:
Product.joins(:restrictions).where.not(restrictions: { name: "CT" }).count
因此,我期望能夠退回我所有的產品,但那些CT受限的產品除外。 但是,它什么也不返回:
Product.last.restrictions
Product Load (0.5ms) SELECT "products".* FROM "products" ORDER BY "products"."id" DESC LIMIT 1
Restriction Load (0.3ms) SELECT "restrictions".* FROM "restrictions" INNER JOIN "product_restrictions" ON "restrictions"."id" = "product_restrictions"."restriction_id" WHERE "product_restrictions"."product_id" = $1 [["product_id", 2559]]
[
#<Restriction:0x007ff0f1dfec58> {
:id => 11,
:category => "US State",
:name => "CT",
:created_at => Wed, 07 Jun 2017 17:57:42 UTC +00:00,
:updated_at => Wed, 07 Jun 2017 17:57:42 UTC +00:00
}
]
[48] pry(main)> Product.count
(0.6ms) SELECT COUNT(*) FROM "products"
2494
[49] pry(main)> Product.joins(:restrictions).where.not(restrictions: { name: "AZ" }).count
(47.8ms) SELECT COUNT(*) FROM "products" INNER JOIN "product_restrictions" ON "product_restrictions"."product_id" = "products"."id" INNER JOIN "restrictions" ON "restrictions"."id" = "product_restrictions"."restriction_id" WHERE ("restrictions"."name" != $1) [["name", "AZ"]]
1
[50] pry(main)> Product.joins(:restrictions).where.not(restrictions: { name: "CT" }).count
(6.7ms) SELECT COUNT(*) FROM "products" INNER JOIN "product_restrictions" ON "product_restrictions"."product_id" = "products"."id" INNER JOIN "restrictions" ON "restrictions"."id" = "product_restrictions"."restriction_id" WHERE ("restrictions"."name" != $1) [["name", "CT"]]
0
我希望最后一個查詢返回2493(僅該最后一個產品有限制),而不是0。我希望AZ查詢返回2494,而不是0。
但是,此引擎sql有效(使用NOT EXISTS):
state = "CT"
Product.where('NOT EXISTS ' \
'(SELECT 1 from restrictions
JOIN product_restrictions
on product_id = products.id
WHERE restrictions.name = ? AND restrictions.category = ?)', state, 'US State'
)
}
aboe查詢返回除CT限制的產品以外的所有產品
問題
當您執行INNER JOIN時,它將創建一個聯接表,其中將僅包含具有相關限制的產品的條目。 “無限制的產品”或“無product_id的限制”將不包括在其中。
在問題中,您提到“僅最后一種產品有限制”。 因此,當您執行JOIN時,它在聯接表中僅創建了1個條目,而當您進一步在限制名稱上添加條件時,您將其刪除。 因此,最終結果為空。
如果即使產品沒有相關限制,也要在連接表中包括產品,請使用LEFT OUTER JOIN。 這是一個有用的鏈接- 內聯接vs左外聯接
解決方案:如果使用rails5:-
Product.left_outer_joins(:restrictions).where.not(restrictions: { name: "CT" }).count
其他
Product.joins("LEFT OUTER JOIN restrictions on restrictions.product_id = products.id").where.not(restrictions: { name: "CT" }).count
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.