Index: handlers/views_handler_field.inc =================================================================== --- handlers/views_handler_field.inc (Revision 9793) +++ handlers/views_handler_field.inc (Arbeitskopie) -48,6 +48,17 @@ 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 @@ */ 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(); } -185,7 +205,38 @@ '#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.'), + ); + + views_include('query'); + $sql_functions = views_query::get_aggregate_functions(); + + $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; $form['alter']['alter_text'] = array( Index: includes/query.inc =================================================================== --- includes/query.inc (Revision 9793) +++ includes/query.inc (Arbeitskopie) -936,6 +936,9 @@ } } + $has_groupby = FALSE; + $groupby_fields = array(); + $has_aggregate = FALSE; $non_aggregates = array(); -952,14 +955,26 @@ // 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[] = $string; + } + if (!empty($field['distinct'])) { $string = "DISTINCT($string)"; } - if (!empty($field['count'])) { - $string = "COUNT($string)"; - $has_aggregate = TRUE; + + $aggregate_functions = $this->get_aggregate_functions($string); + foreach ($aggregate_functions as $key => $aggregate_function) { + if (!empty($field[$key])) { + $string = $aggregate_function; + $has_aggregate = TRUE; + break; + } } - else if (!empty($field['aggregate'])) { + + if (!$has_aggregate && !empty($field['aggregate'])) { $has_aggregate = TRUE; } elseif ($this->distinct && !in_array($fieldname, $this->groupby)) { -979,8 +995,8 @@ } } - 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'); } -1016,5 +1032,30 @@ } return $args; } + + /** + * Get the available aggregate functions for the current DB + * backend. + */ + static function get_aggregate_functions($string = FALSE) { + $functions = array(); + // Add ANSI functions + if (!$string) { + $functions['average'] = t('Average'); + $functions['sum'] = t('Sum'); + $functions['count'] = t('Count'); + $functions['minimum'] = t('Minimum'); + $functions['maximum'] = t('Maximum'); + } + else { + $functions['average'] = "AVG($string)"; + $functions['sum'] = "SUM($string)"; + $functions['count'] = "COUNT($string)"; + $functions['minimum'] = "MIN($string)"; + $functions['maximum'] = "MAX($string)"; + } + + return $functions; + } }