Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Added cross tabulation method to ActiveRecord::Base

#1542

A cross tabulation compares one variable against the tabulation of another variable. This is often useful when you need to aggregate data in categories.

For example, you may want to find the sum of sales for each department in a supermarket. Given the schema:

 Departments: id, name
 Sales: id, department_id, amount

and the example data:

Departments:
 +------------------+
 | id |    name     |
 |----+-------------+
 | 1  | Vegetables  |
 | 2  | Deli        |
 | 3  | Frozen      |
 +------------------+

Sales:
 +-----------------------------+
 | id | department_id | amount |
 |----+---------------+--------+
 | 1  |       1       | 11     |
 | 1  |       1       | 111    |
 | 2  |       2       | 22     |
 | 2  |       2       | 222    |
 | 3  |       3       | 3      |
 +-----------------------------+

You would want the output:
 +----------------------------+
 | Vegetables | Deli | Frozen |
 |------------+------+--------+
 |    122     |  244 |   3    |
 +----------------------------+

Which could be achieved using the method call:
 Department.cross('name', :aggregator => 'sum', aggregator_column => 'amount', :joins => 'INNER JOIN sales ON sales.department_id = departments.id')

Reported by Alex Pooley · December 10th, 2008 @ 05:22 AM

State: wontfix
Milestone: 2.x
Assigned to: nobody
Importance: none

Activity

  1. Alex Pooley
    Alex Pooley

    Let me try that again - and if this doesn't work then please just read the diff as this "comment" is straight from there :)

    A cross tabulation compares one variable against the tabulation of another variable. This is often useful when you need to aggregate data in categories.

    For example, you may want to find the sum of sales for each department in a supermarket. Given the schema:

    Departments: id, name Sales: id, department_id, amount

    and the example data:

    Departments: +------------------+ | id | name | |----+-------------+ | 1 | Vegetables | | 2 | Deli | | 3 | Frozen | +------------------+

    Sales: +-----------------------------+ | id | department_id | amount | |----+---------------+--------+ | 1 | 1 | 11 | | 1 | 1 | 111 | | 2 | 2 | 22 | | 2 | 2 | 222 | | 3 | 3 | 3 | +-----------------------------+

    You would want the output: +----------------------------+ | Vegetables | Deli | Frozen | |------------+------+--------+ | 122 | 244 | 3 | +----------------------------+

    Which could be achieved using the method call:

    Department.cross('name', :aggregator => 'sum', aggregator_column => 'amount', :joins => 'INNER JOIN sales ON sales.department_id = departments.id')
    
    

    December 10th, 2008 @ 05:27 AM

  2. Frederick Cheung
    Frederick Cheung

    I'm not entirely sure what you gain over doing

    
    Department.sum :amount, :joins => :sales, :group => 'departments.name'
    

    December 10th, 2008 @ 10:00 AM

  3. Alex Pooley
    Alex Pooley

    Sorry, maybe I should swap the example in the doc for the method. One of the test cases is probably a better example...

    @@@ruby def test_cross_with_joins_and_group_and_aggregator

    # "Show me the number of comments an author receives based on post type"
    cross = Comment.cross('posts.type', :joins => 'INNER JOIN posts ON comments.post_id = posts.id', :group => 'posts.author_id', :aggregator_column => 'comments.id')
    assert_equal(
      [{"Post"=>"6", "SpecialPost"=>"1", "StiPost"=>"2", "author_id"=>"1"},
       {"Post"=>"1", "SpecialPost"=>"0", "StiPost"=>"0", "author_id"=>"2"}],
      cross)
    
    

    end

    
    
    As you can see, we've grouped by author, but then further separated the post count by the type of post.
    
    I hope this helps.
    

    December 10th, 2008 @ 10:19 AM

  4. Frederick Cheung
    Frederick Cheung

    You might find that discussing this on the core list is the best way to achieve a consensus. Personally I don't think this belongs in core (although some may find it useful as a plugin) but that's just may opinion.

    December 10th, 2008 @ 12:56 PM

  5. Alex Pooley
    Alex Pooley

    Yes, I'm still in two minds as to whether it should be included as core Rails.

    I'll ping the list, but I think I'll built out a plugin anyway as there's a lot more you could do with a feature like this that probably excludes it from core activerecord functionality.

    December 10th, 2008 @ 10:00 PM

  6. Alex Pooley
    Alex Pooley

    On second thoughts I've decided not to contact the core group. I think a plugin will be a better fit.

    December 11th, 2008 @ 08:24 AM

  7. Jeremy Kemper
    Jeremy Kemper
    • State changed from new to wontfix

    December 12th, 2008 @ 12:45 AM

  8. Ryan Bigg
    Ryan Bigg
    • Tag cleared.

    Automatic cleanup of spam.

    October 9th, 2010 @ 10:01 PM

  9. Ryan Bigg
    Ryan Bigg

    Automatic cleanup of spam.

    October 11th, 2010 @ 12:11 PM

  10. bingbing