I like to generate a sales report. Therefore I like to group by the orders by the date and then build the sum over the group.

The group by works, but the result is only all selected items and not on the group defined by the grouping field.

Is this supported by views? If yes, how do I need to configure the view?

Comments

merlinofchaos’s picture

Status: Active » Postponed (maintainer needs more info)

I'm sorry, I'm having trouble understanding what precisely is the problem. Can you be more specific about what fields you've added and configured and how they behave vs how you expect them to behave? Then mark this issue active again when complete.

Note: There is a known problem right now with grouping on fields that can be multiple, i.e, more than 1 value per entity. See http://drupal.org/node/1089694 though that doesn't sound like what you're describing.

hunziker’s picture

Status: Postponed (maintainer needs more info) » Active

You're absolutely right, it is not clear what I have written. So I try it again. I think an example will clarify what I mean.

We have the entity (table) orders:

OrderID OrderDate OrderTotalAmount
10001 2011-03-03 55.00
10002 2011-04-06 295.00
10003 2011-05-07 157.00
10004 2011-03-09 125.00
10005 2011-04-03 27.00
10006 2011-05-08 345.00
10007 2011-03-12 65.00
10008 2011-04-15 78.00
10009 2011-03-23 56.00
10010 2011-04-17 43.00
10011 2011-05-13 38.00

If you use the group by feature you can sum (or use other aggregation functions) to generate some aggregated fields. If we use the sum function over the OrderTotalAmount we get a single field with the value of 1'281.00. Its equals more or less the SQL Statement:

SELECT sum(Order Total Amount) FROM orders;

I know the views module joins some fields into it, but for describing my problem, we can abstract from this fact.

The shown aggregation is ok when you look for the whole sum. But normally you intent to do something like:

SELECT sum(OrderTotalAmount), OrderDate FROM orders GROUP BY OrderDate;

If we assume, we can specify the granularity (month) of the OrderDate we get something like this:

OrderDate Sum for this month
March 301.00
April 365.00
May 540.00

Is it possible to do such aggregations with Views? I hope the question is now more clear and understandable.

merlinofchaos’s picture

Status: Active » Fixed

It certainly should be possible to do this. If you create your view with just those two fields (order total and order date), and enable the group by setting in the advanced set, you will then be able to get to the group by settings on each field.

You then should be able to change the group by settings on the ordertotal to sum, and leave the orderdate as is.

THAT said, because what you're grouping on is a date, it requires date.module to be pretty cognizant of what is going on here, because you need to set the granularity actually in the database so that it can be grouped on. It's possible that date.module isn't smart enough to realize it has to do that.

If that's the entire problem, then you need to move this issue to date.module.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

hunziker’s picture

Category: support » feature
Status: Closed (fixed) » Active

Sorry when I reopen this issue. I check it out in more detail. The problem is the views module itself. The date is stored as a UNIX timestamp. Therefor the core views handlers are used (filter, field and sort uses all views_handler_sort_date, views_handler_filter_date, views_handler_field_date respectively).

I change the issue from support request to feature request, because this feature is missing in the views core. I would like to provide a patch for this, but it is not that easy.

There seems no easy way to determine if a field is going to be added as "group by". The group by is added in plugins/views_plugin_query_default.inc on line 1200. If a field is added as group by is determine on line 1081. If we can determine if a field is going to be used in group by, then we could change the formatting. This could be then a part of handlers/views_handler_field_date.inc.

Can some one put me in the right direction?

FYI: This issue seems to be related to this one:
#1159786: group by time ranges: years, quarters, months, weeks, days, hours, etc.

dawehner’s picture

Something like this should be possible, see


SELECT DATE_FORMAT(postdate, '%Y-%m-%d') AS dd, COUNT(id) FROM MyTable GROUP BY dd;
hunziker’s picture

Thank you. My problem is how to build such a query with views. How it needs to look like is clear.

Since you have normally UNIX timestamps for dates you need to do it like this:

SELECT DATE_FORMAT(FROM_UNIXTIME(postdate), '%Y-%m-%d') AS dd, COUNT(id) FROM MyTable GROUP BY dd;

or this would also work:

SELECT postdate AS dd, COUNT(id) FROM MyTable GROUP BY DATE_FORMAT(FROM_UNIXTIME(dd), '%Y-%m-%d');

We have two problems here:

  1. Group by with date is database vendor specific. For MySQL the above solutions are valid, for different vendors (such as PostgreSQL) its different.)
  2. The code of views isn't that flexible to add a database vendor specific addition for group by statements. There is no hook or API for such a thing.

I see one simple solution to this problem:
In the date field handler we add the field twice, once we use it for formatting and once we use it for internal use (such as group by). The formatting can be controlled fully by the field handler, so we could simply take the second field. For default we use the database formatted version.

The query would look like this:

SELECT DATE_FORMAT(FROM_UNIXTIME(postdate), '%Y-%m-%d') AS postdate_default, postdate AS postdate_second, COUNT(id) FROM MyTable GROUP BY postdate_default;

Has the solution described above a chance to be committed into the views core? There is some sort of redundancy in it.

dawehner’s picture

There is some db specific code here already: views_date_sql_field perhaps a new function could be added as well.

hunziker’s picture

I'm not sure which file / class you mean. I found in the date module the file:
date/date_api/date_api_sql.inc

There is all the code required to implement this for specific database vendor. (Convert UNIX timestamp to date, format it and build the granularity form.)

But then the views module is depending on Date. Should we move this functionally into a separate module to avoid new dependencies for Views?

Proposed Approach: We could override all the date fields with a custom date field handler. This new handler then adds the required code. Perhaps we need some changes in the core to allow insertion of this new code.