簡體   English   中英

SQL,Arel和過濾記錄問題。 軌。 可以使用一些建議

[英]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限制的產品以外的所有產品

問題

  1. 為什么使用聯接的第一個查詢不起作用?
  2. 我如何在這里變得更好? 有沒有關於sql的好書?
  3. 有沒有一種更好的方式可以編寫不使用類似SQL字符串的解決方案?

當您執行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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM