我正在建造一些购物车。某些产品(并非全部)可以兑换,如redeemable
表中的products
字段所示。
兑换产品时,redeemed_qty
和location_id
会在line_item_states
表中设置为一行。这允许两件事:
我尝试创建一个报告,列出所有line_items
,但line_item_states
增强/扩展。
例如,根据下面的数据,它应该列出LineItem 3次:
Product | Redeemed? | Qty | Location
Full Yard Landscaping | No | 4 | 2
Full Yard Landscaping | Yes | 8 | 3
Full Yard Landscaping | Yes | 2 | 1
它已列出3次,因为line_item_states
的{{1}}按位置分组,其line_item
求和。
我能够在没有第一行的情况下实现上表BUT。这是具有计算的剩余未兑换数量的行。所以基本上是某种虚拟行?
这是我当前查询生成上表(没有第一行):
redeemed_qty
如何展开查询以生成示例表中的第一行?
它甚至可能吗?我看错了吗?
的LineItem:
LineItem.select('"line_items".*,
COALESCE("locs"."location_id", "products"."location_id") "location_id",
COALESCE("locs"."rqty", "line_items"."qty") "lqty",
"locs"."rqty" "qty_redeemed"')
.joins('LEFT OUTER JOIN
(SELECT "lie"."line_item_id",
"lie"."location_id",
SUM("lie"."redeemed_qty") "rqty"
FROM "line_item_states" "lie"
GROUP BY "lie"."line_item_id", "lie"."location_id") "locs"
ON ("line_items"."id" = "locs"."line_item_id")
LEFT OUTER JOIN "products"
ON "products"."id" = "line_items"."product_id"')
产品:
#<LineItem id: 24, order_id: 19, product_id: 3, created_at: "2014-08-20 01:27:53", updated_at: "2014-08-21 05:51:51", qty: 14, discount: #<BigDecimal:7ff0ba69e238,'0.0',9(18)>, discount_type: nil, price: #<BigDecimal:7ff0ba69e0f8,'0.1069E3',18(18)>, total: #<BigDecimal:7ff0ba69e030,'0.14966E4',18(18)>>
LineItemState:
#<Product id: 3, title: "Full Yard Landscaping", full_price: #<BigDecimal:7ff0ba4d6400,'0.299E3',9(18)>, created_at: "2014-08-18 02:23:25", updated_at: "2014-08-21 05:50:56", price_overridable: true, deposit_price: #<BigDecimal:7ff0ba4d5910,'0.11E3',9(18)>, gvable: true, redeemable: true, location_id: 2>
模式
[#<LineItemState id: 51, redeemed_qty: 1, location_id: 1, user_id: 1, created_at: "2014-08-21 05:26:33", updated_at: "2014-08-21 05:26:33", line_item_id: 24, notes: nil>,
#<LineItemState id: 52, redeemed_qty: 1, location_id: 3, user_id: 1, created_at: "2014-08-21 05:26:56", updated_at: "2014-08-21 05:26:56", line_item_id: 24, notes: nil>,
#<LineItemState id: 53, redeemed_qty: 2, location_id: 3, user_id: 1, created_at: "2014-08-21 05:30:30", updated_at: "2014-08-21 05:30:30", line_item_id: 24, notes: nil>,
#<LineItemState id: 54, redeemed_qty: 1, location_id: 3, user_id: 1, created_at: "2014-08-21 05:31:08", updated_at: "2014-08-21 05:31:08", line_item_id: 24, notes: nil>,
#<LineItemState id: 55, redeemed_qty: 1, location_id: 3, user_id: 1, created_at: "2014-08-21 05:31:22", updated_at: "2014-08-21 05:31:22", line_item_id: 24, notes: nil>,
#<LineItemState id: 56, redeemed_qty: 1, location_id: 3, user_id: 1, created_at: "2014-08-21 05:31:59", updated_at: "2014-08-21 05:31:59", line_item_id: 24, notes: nil>,
#<LineItemState id: 57, redeemed_qty: 1, location_id: 3, user_id: 1, created_at: "2014-08-21 05:58:21", updated_at: "2014-08-21 05:58:21", line_item_id: 24, notes: nil>,
#<LineItemState id: 58, redeemed_qty: 1, location_id: 3, user_id: 1, created_at: "2014-08-21 06:03:34", updated_at: "2014-08-21 06:03:34", line_item_id: 24, notes: nil>,
#<LineItemState id: 59, redeemed_qty: 1, location_id: 1, user_id: 1, created_at: "2014-08-21 06:04:20", updated_at: "2014-08-21 06:04:20", line_item_id: 24, notes: "Another cool message dude!">]
模型
create_table "products", force: true do |t|
t.string "title"
t.decimal "full_price", precision: 7, scale: 2, default: 0.0
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "price_overridable", default: false
t.decimal "deposit_price", precision: 7, scale: 2, default: 0.0
t.boolean "gvable", default: false
t.boolean "redeemable", default: false
t.integer "location_id"
end
模式
class Product < ActiveRecord::Base
has_many :line_items
belongs_to :location
end
模型
create_table "line_items", force: true do |t|
t.integer "order_id"
t.integer "product_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "qty", limit: 8, default: 1
t.decimal "discount", precision: 7, scale: 2, default: 0.0
t.string "discount_type"
t.decimal "price", precision: 7, scale: 2, default: 0.0
t.decimal "total", precision: 7, scale: 2, default: 0.0
end
模式
class LineItem < ActiveRecord::Base
belongs_to :product
has_many :line_item_states
end
模型
create_table "line_item_states", force: true do |t|
t.integer "redeemed_qty"
t.integer "location_id"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "line_item_id"
t.text "notes"
end
答案 0 :(得分:1)
我建议您使用CTE计算兑换数量。在用于从基本数量中减去的主查询中,并使用UNION ALL
附加计算的行。
使用一组基本列,查询可能如下所示:
WITH cte AS (
SELECT line_item_id, location_id, SUM(redeemed_qty) AS qty
FROM line_item_states
GROUP BY line_item_id, location_id
)
SELECT FALSE AS redeemed, li.id AS line_item_id, li.location_id
,CASE WHEN r.qty IS NULL THEN li.qty ELSE li.qty - r.qty END AS qty
FROM line_items li
LEFT JOIN (
SELECT line_item_id, sum(qty) AS qty
FROM cte
GROUP BY 1
) r ON r.line_item_id = li.id
UNION ALL
SELECT TRUE, c.line_item_id, COALESCE(c.location_id, p.location_id), c.qty
FROM cte c
JOIN line_items li ON li.id = l.line_item_id
LEFT JOIN products p ON p.id = li.product_id;