diff -urp views/handlers/views_handler_field.inc views/handlers/views_handler_field.inc --- views/handlers/views_handler_field.inc 2009-06-03 15:55:52.000000000 -0400 +++ views/handlers/views_handler_field.inc 2009-09-01 12:20:15.109375000 -0400 @@ -48,6 +48,17 @@ class views_handler_field extends views_ return TRUE; } + /** + * Determine if this field can be aggregated over. + * + * Fields can set this to FALSE if they do not wish to allow + * aggregation functions (such as COUNT, SUM, MAX, etc.) to be + * used on this field. + */ + function allow_aggregation() { + return TRUE; + } + function init(&$view, $options) { parent::init($view, $options); @@ -61,9 +72,18 @@ class views_handler_field extends views_ */ function query() { $this->ensure_my_table(); - // Add the field. + + // Add the field, taking care of any aggregation that + // may affect it. $this->field_alias = $this->query->add_field($this->table_alias, $this->real_field); + if ($this->options['groupby']) { + $this->query->fields[$this->field_alias]['groupby'] = TRUE; + } + if ($this->options['aggregate']['aggregate_field']) { + $this->query->fields[$this->field_alias][$this->options['aggregate']['sql_function']] = TRUE; + } + $this->add_additional_fields(); } @@ -181,6 +201,43 @@ class views_handler_field extends views_ '#default_value' => $this->options['exclude'], '#description' => t('Check this box to not display this field, but still load it in the view. Use this option to not show a grouping field in each record, or when doing advanced theming.'), ); + $form['groupby'] = array( + '#type' => 'checkbox', + '#title' => t('Group this field'), + '#default_value' => $this->options['groupby'], + '#description' => t('Check this box if you want to group (summarize) this field and (optionally) aggregate another field.'), + ); + + if ($this->allow_aggregation()) { + $form['aggregate']['#tree'] = TRUE; + $form['aggregate']['aggregate_field'] = array( + '#type' => 'checkbox', + '#title' => t('Aggregate this field'), + '#default_value' => $this->options['aggregate']['aggregate_field'], + '#description' => t('Check this box if you want to apply an aggregation function (such as a count, average) to the values in this field.'), + ); + + $sql_functions = array( + 'count' => t('Count'), + 'sum' => t('Sum'), + 'average' => t('Average'), + 'minimum' => t('Minimum'), + 'maximum' => t('Maximum'), + 'concat' => t('Concatenate'), + ); + + $form['aggregate']['sql_function'] = array( + '#type' => 'select', + '#title' => t('Aggregation function'), + '#default_value' => $this->options['aggregate']['sql_function'], + '#description' => t('The function that should be applied to the values in this field.'), + '#options' => $sql_functions, + '#process' => array('views_process_dependency'), + '#dependency' => array( + 'edit-options-aggregate-aggregate-field' => array(1) + ), + ); + } if ($this->allow_advanced_render()) { $form['alter']['#tree'] = TRUE; diff -urp views/includes/query.inc views/includes/query.inc --- views/includes/query.inc 2009-06-02 14:17:06.000000000 -0400 +++ views/includes/query.inc 2009-09-01 12:23:51.312500000 -0400 @@ -912,6 +912,9 @@ class views_query { } } + $has_groupby = FALSE; + $groupby_fields = array(); + $has_aggregate = FALSE; $non_aggregates = array(); @@ -928,6 +931,12 @@ class views_query { // store for use with non-aggregates below $fieldname = (!empty($field['alias']) ? $field['alias'] : $string); + // check for and store group by fields + if(!empty($field['groupby'])) { + $has_groupby = TRUE; + $groupby_fields[] = $fieldname; + } + if (!empty($field['distinct'])) { $string = "DISTINCT($string)"; } @@ -935,6 +944,26 @@ class views_query { $string = "COUNT($string)"; $has_aggregate = TRUE; } + else if (!empty($field['sum'])) { + $string = "SUM($string)"; + $has_aggregate = TRUE; + } + else if (!empty($field['average'])) { + $string = "AVG($string)"; + $has_aggregate = TRUE; + } + else if (!empty($field['minimum'])) { + $string = "MIN($string)"; + $has_aggregate = TRUE; + } + else if (!empty($field['maximum'])) { + $string = "MAX($string)"; + $has_aggregate = TRUE; + } + else if (!empty($field['concat'])) { + $string = "GROUP_CONCAT($string SEPARATOR ', ')"; + $has_aggregate = TRUE; + } else if (!empty($field['aggregate'])) { $has_aggregate = TRUE; } @@ -952,8 +981,8 @@ class views_query { } } - if ($has_aggregate || $this->groupby) { - $groupby = "GROUP BY " . implode(', ', array_unique(array_merge($this->groupby, $non_aggregates))) . "\n"; + if ($has_aggregate || $has_groupby || $this->groupby) { + $groupby = "GROUP BY " . implode(', ', array_unique($has_groupby ? $groupby_fields : array_merge($this->groupby, $non_aggregates))) . "\n"; if ($this->having) { $having = $this->condition_sql('having'); }