On Friday, November 8, 2013 12:08:25 PM UTC-8, Snarke wrote:

> I'm staring at the last section of the "Advanced Associations" 
> documentation, which says "you can use Sequel‘s association support to get 
> aggregate information for columns in associated tables (sums, averages, 
> etc.)" 
>
> Yup, that's what I want to do. But the provided example is absolutely 
> baffling me. Truncated code for my case as follows: 
>
>         TABLE skus ( 
>                 id uuid DEFAULT uuid_generate_v1() NOT NULL, 
>                 name varchar, 
>                 PRIMARY KEY (id) 
>         ); 
>
>         TABLE items ( 
>                 id uuid DEFAULT uuid_generate_v1() NOT NULL, 
>                 sku_id uuid NOT NULL, 
>                 quantity int4, 
>                 PRIMARY KEY (id) 
>         ); 
>
> An "item" is an invoice line item. If one row of the 'skus' table is for a 
> brown chair, there will be 0 or more rows in 'items' that indicate I have 
> sold/shipped various quantities of brown chairs to some number of people. 
> There's the obvious foreign key between sku_id and skus.id. 
>
>         class Sku < Sequel::Model 
>                 one_to_many :items 
>         end 
>
>         class Item < Sequel::Model 
>                 many_to_one :sku 
>         end 
>
> What I'd like to do is be able to retrieve a set of skus and the sum of 
> the quantity field of the associated items. In other words "Sku A, and I've 
> shipped xx of them. Sku B, and I've shipped yy of them," et cetera. I can 
> certainly do that in ways that require lots of queries, but I can't quite 
> wrap my head around how create the Sequel equivalent of 
>
>         select skus.*, sum(items.quantity) 
>         from skus join items on (skus.id=sku_id) 
>         group by skus.* 
>
> which isn't actually valid SQL code, I know. It could also be 
>
>         select *, 
>         (select sum(quantity) from items where sku_id = skus.id) 
>         from skus 
>

The latter approach is fairly easy to do if you just want to use a single 
query:

  
Sku.select_append(Item.select{sum(:quantity)}.where(:sku_id=>:skus__id).as(:quantity)).all

The join and group by approach is possible as well, but more work.

The eager loader in the Advanced Associations example looks pretty similar 
to what you want, here's an untested version:

  class Sku < Sequel::Model
    one_to_many :items
    many_to_one :item_quantities, :read_only=>true, :key=>:id,
    
 :dataset=>proc{Item.where(:sku_id=>id).select{sum(quantity).as(quantity)}},
     :eager_loader=>(proc do |eo|
      eo[:rows].each{|p| p.associations[:item_quantities] = nil}
      Item.where(:sku_id=>eo[:id_map].keys).
       select_group(:sku_id).
       select_append{sum(quantity).as(quantity)}.
       all do |t|
        p = eo[:id_map][t.values.delete(:sku_id)].first
        p.associations[:item_quantities] = t
       end
     end)
    def item_quantities
      if s = super
        s[:quantity]
      end
    end
  end
  class Item < Sequel::Model
    many_to_one :sku
  end

Note that this is different than your SQL queries, as it only returns the 
sum of the quantities, not the sum of the quantities plus the object's 
values. The associations code allows you to do:

  sku = Sku[1]
  sku.item_quantities # Sum of quantity for this sku's items in 1 query

The eager loader makes it so:

  Sku.eager(:item_quantities).all # 2 queries
  Sku.map{|s| s.item_quantities} # 0 queries

Thanks,
Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to