This project is archived and is in readonly mode.

#1542 ✓wontfix
Alex Pooley

Added cross tabulation method to ActiveRecord::Base

Reported by Alex Pooley | December 10th, 2008 @ 05:22 AM | in 2.x

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')

Comments and changes to this ticket

  • Alex Pooley

    Alex Pooley December 10th, 2008 @ 05:27 AM

    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')
    
    
  • Frederick Cheung

    Frederick Cheung December 10th, 2008 @ 10:00 AM

    I'm not entirely sure what you gain over doing

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

    Alex Pooley December 10th, 2008 @ 10:19 AM

    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.
    
  • Frederick Cheung

    Frederick Cheung December 10th, 2008 @ 12:56 PM

    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.

  • Alex Pooley

    Alex Pooley December 10th, 2008 @ 10:00 PM

    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.

  • Alex Pooley

    Alex Pooley December 11th, 2008 @ 08:24 AM

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

  • Jeremy Kemper

    Jeremy Kemper December 12th, 2008 @ 12:45 AM

    • State changed from “new” to “wontfix”
  • Ryan Bigg

    Ryan Bigg October 9th, 2010 @ 10:01 PM

    • Tag cleared.

    Automatic cleanup of spam.

  • Ryan Bigg

    Ryan Bigg October 11th, 2010 @ 12:11 PM

    Automatic cleanup of spam.

  • bingbing

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Attachments

Pages