2010-06-29 30 views
6

Bir envanter sistemi tasarlıyorum, o kullanıcıları, ürünler, buy_leads, emir (yetkili buy_leads), girişler ve çıkışları sahiptir.Envanter SQL Sorgu?

class Product < ActiveRecord::Base 
    has_many :buy_leads 
end 

class BuyLead < ActiveRecord::Base 
    belongs_to :product 
    has_one :order 
end 

class Order < ActiveRecord::Base 
    belongs_to :buy_lead 
    belongs_to :user, :foreign_key => :authorized_by 
    has_many :inputs 
end 

class Input < ActiveRecord::Base 
    belongs_to :order 
    has_many :outputs 
end 

class Output < ActiveRecord::Base 
    # Associations 
    belongs_to :input 
    belongs_to :user 
end 

giriş ve çıkışları bir miktar değerine sahiptir. çıkışları miktarları olumsuz yaparak ürünler envanteri ve spesifik ürün envanteri ben, iki çiğ SQL sorguları UNION olsun ve sonra grubu ve hepsini bir araya Özetle:

Çalışıyor
class InventoryController < ApplicationController 

    def index 
    @inventory = Input.find_by_sql products_inventory_sql 
    end 

    def show 
    @inventory = Input.find_by_sql product_inventory_sql(params[:id]) 
    end 

private 

    def inputs_sql 
    "SELECT b.*, p.*, i.order_id, 
      i.id AS input_id, 
      i.quantity AS quantity  
    FROM inputs i 
      JOIN orders r ON r.id = i.order_id 
      JOIN buy_leads b ON b.id = r.buy_lead_id 
      JOIN products p ON p.id = b.product_id" 
    end 

    def outputs_sql 
    "SELECT b.*, p.*, i.order_id, 
      i.id AS input_id, 
      (o.quantity * -1) AS quantity 
    FROM outputs o 
      JOIN inputs i ON i.id = o.input_id 
      JOIN orders r ON r.id = i.order_id 
      JOIN buy_leads b ON b.id = r.buy_lead_id 
      JOIN products p ON p.id = b.product_id" 
    end 

    def products_inventory_sql 
    "SELECT *, SUM(quantity) AS remaining_qty 
    FROM (#{inputs_sql} UNION #{outputs_sql}) 
    GROUP BY product_id" 
    end 

    def product_inventory_sql(id) 
    "SELECT *, SUM(quantity) AS remaining_qty 
    FROM (#{inputs_sql} UNION #{outputs_sql}) 
    WHERE product_id = #{id} 
    GROUP BY order_id, input_id" 
    end 

end 

,

Product.inputs.by_product(id) 
Product.inventory.by_product(id) 
... 

Herhangi fikirler, ya da ben h yapın: ama ActiveRecord zincir sorgularına named_scope özelliklerini kullanmak ve benzeri şeyler yapabilmek istiyorum Şemayı daha uygun bir şekilde değiştirmek için ave? Teşekkürler!

cevap

2

Bunu çözmek için çok fazla olasılık var, bu raporlardan tam olarak ne istiyorsunuz?

Satınalma siparişi? ürünler? girişler/çıkışlar?

GÜNCELLEME

bu

deneyin

(beni aydınlat lütfen eğer ben sorunuza yorum yapamam çünkü cevap olarak bu mesaj, ben cevap güncelleriz)

#on input 
named_scope :by_product, lambda {|id| {:joins => {:orders => {:buy_leads => :products}}, :conditions => ['products.id = ?', id]}} 

ve

Input.by_product(25) 
arayarak o ürün kimliği maç girdileri alabilirsiniz

Eğer aradığınız şey buysa, çıktıları şu anda ürünlere göre üretmeyi başarabileceğinizi düşünüyorum:]

+0

(girişler - çıkışlar), Ürüne göre –

0

Ben veriler olmadan bu test edemez ama O böyle bir şey olması gerektiğini düşünüyorum:

SELECT 
     b.*, p.*, i.order_id, i.id AS input_id, i.quantity AS quantity, -o.quantity AS quantity, 
     (i.quantity - COALESCE(o.quantity,0)) AS remaining_qty 
FROM 
     products p 
     JOIN buy_leads b ON b.product_id = p.id 
     JOIN orders r ON r.buy_lead_id = b.id 
     JOIN inputs i ON i.order_id = r.id 
     LEFT JOIN outputs o ON o.input_id = i.id 
0
Victor'un çözüm İKİ girişlerine tarafından ürünlerini çoğaltmak olacaktır katılmak çünkü birden fazla "çıktı" kaydı olduğundan başarısız

ve çıkışlar. Bunun yerine, gerçek tablo yerine türetilmiş bir tablo kullanarak JOIN kullanmalısınız. Bunun zor olduğunu veri olmadan test etmek ve göstermek ama böyle bir şey çalışıyor olmalıdır için:

"SELECT b.*, p.*, i.order_id, 
     i.id AS input_id, 
     i.quantity AS quantity, 
ISNULL(z.negquantities,0) negquantities, 
i.quantity + ISNULL(z.negquantities,0) sumquantities 

FROM inputs i 
     JOIN orders r ON r.id = i.order_id 
     JOIN buy_leads b ON b.id = r.buy_lead_id 
     JOIN products p ON p.id = b.product_id 
    JOIN 
    (SELECT SUM(-1 * o.quantity) NegQuantities, o.input_id FROM outputs o GROUP BY o.input_id) z 
    ON z.input_id = i.id 

Sen ziyade çıkış yerine, giriş kimliğiyle gruplandırılmış, çıktı tablosunun toplam toplamını katılmadan görüyoruz masanın kendisi. Bu, katılmalarınızda istenmeyen satır kopyalarını ortadan kaldırır. Tabii ki, "ON" listesine veya türetilmiş tablonun "Where" ibaresine daha fazla eleman ekleyebilirsiniz ("z" denir) Bu yol sizi en iyi şekilde bulacaktır. Alternatif olarak, bir DB diyagramı gönderin böylece tablo ilişkilerinizi daha iyi anlıyoruz.

+0

her iki yaklaşım da doğru gibi görünüyor, ancak daha basit hale getirmiyorlar. Kapsamları –

+0

sorgusu saklı bir yordama yerleştirmek için? Sanırım ne aradığınızdan emin değilim? – Matthew