   {
     case GDF_INT8:   
       { 
-        return dispatched_groupby<groupby_type, int8_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                            out_groupby_columns, out_aggregation_column, sort_result);
+        return typed_groupby<int8_t, op>(groupby_input_table, 
+                                         in_aggregation_column, 
+                                         groupby_output_table, 
+                                         out_aggregation_column, 
+                                         sort_result);
       }
     case GDF_INT16:  
       { 
-        return dispatched_groupby<groupby_type, int16_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                             out_groupby_columns, out_aggregation_column, sort_result);
+        return typed_groupby<int16_t, op>(groupby_input_table, 
+                                          in_aggregation_column, 
+                                          groupby_output_table, 
+                                          out_aggregation_column, 
+                                          sort_result);
       }
     case GDF_INT32:  
       { 
-        return dispatched_groupby<groupby_type, int32_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                             out_groupby_columns, out_aggregation_column, sort_result);
+        return typed_groupby<int32_t, op>(groupby_input_table, 
+                                          in_aggregation_column, 
+                                          groupby_output_table, 
+                                          out_aggregation_column, 
+                                          sort_result);
       }
     case GDF_INT64:  
       { 
-        return dispatched_groupby<groupby_type, int64_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                             out_groupby_columns, out_aggregation_column, sort_result);
+        return typed_groupby<int64_t, op>(groupby_input_table, 
+                                          in_aggregation_column, 
+                                          groupby_output_table, 
+                                          out_aggregation_column, 
+                                          sort_result);
       }
     case GDF_FLOAT32:
       { 
-        return dispatched_groupby<groupby_type, float, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                            out_groupby_columns, out_aggregation_column, sort_result);
+        return typed_groupby<float, op>(groupby_input_table, 
+                                        in_aggregation_column, 
+                                        groupby_output_table, 
+                                        out_aggregation_column, 
+                                        sort_result);
       }
     case GDF_FLOAT64:
       { 
-        return dispatched_groupby<groupby_type, double, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                           out_groupby_columns, out_aggregation_column, sort_result);
+        return typed_groupby<double, op>(groupby_input_table, 
+                                         in_aggregation_column, 
+                                         groupby_output_table, 
+                                         out_aggregation_column, 
+                                         sort_result);
+      }
+    case GDF_DATE32:    
+      {
+        return typed_groupby<int32_t, op>(groupby_input_table, 
+                                          in_aggregation_column, 
+                                          groupby_output_table, 
+                                          out_aggregation_column, 
+                                          sort_result);
+      }
+    case GDF_DATE64:   
+      {
+        return typed_groupby<int64_t, op>(groupby_input_table, 
+                                          in_aggregation_column, 
+                                          groupby_output_table, 
+                                          out_aggregation_column, 
+                                          sort_result);
+      }
+    case GDF_TIMESTAMP:
+      {
+        return typed_groupby<int64_t, op>(groupby_input_table, 
+                                          in_aggregation_column, 
+                                          groupby_output_table, 
+                                          out_aggregation_column, 
+                                          sort_result);
       }
     default:
-      std::cout << "Unsupported aggregation column type: " << aggregation_column_type << std::endl;
+      std::cerr << "Unsupported aggregation column type: " << aggregation_column_type << std::endl;
       return GDF_UNSUPPORTED_DTYPE;
   }
 }
 
-/* --------------------------------------------------------------------------*/
-/** 
- * @Synopsis  Helper function for gdf_group_by hash. Deduces the type of the input
- * group by gdf_column and sets a template parameter accordingly to another dispatch
- * dispatch function.
- * 
- */
-/* ----------------------------------------------------------------------------*/
-template <template <typename T> class op>
-gdf_error dispatch_groupby_type(int ncols,               
-                                gdf_column* in_groupby_columns[],        
-                                gdf_column* in_aggregation_column,       
-                                gdf_column* out_groupby_columns[],
-                                gdf_column* out_aggregation_column,
-                                bool sort_result = false)
-{
-  gdf_dtype groupby_column_type = in_groupby_columns[0]->dtype;
-
-  // Deduce the type of the groupby column and call function to deduce the aggregation column type
-  switch(groupby_column_type)
-  {
-    case GDF_INT8:   
-      {
-        return dispatch_aggregation_type<int8_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                     out_groupby_columns, out_aggregation_column, sort_result);
-      }
-    case GDF_INT16:  
-      { 
-        return dispatch_aggregation_type<int16_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                      out_groupby_columns, out_aggregation_column, sort_result);
-      }
-    case GDF_INT32:  
-      { 
-        return dispatch_aggregation_type<int32_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                      out_groupby_columns, out_aggregation_column, sort_result);
-      }
-    case GDF_INT64:  
-      { 
-        return dispatch_aggregation_type<int64_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                      out_groupby_columns, out_aggregation_column, sort_result);
-      }
-    // For floating point groupby column types, cast to an integral type
-    case GDF_FLOAT32:
-      {
-        return dispatch_aggregation_type<int32_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                      out_groupby_columns, out_aggregation_column, sort_result);
-      }
-    case GDF_FLOAT64:
-      { 
-        return dispatch_aggregation_type<int64_t, op>(ncols, in_groupby_columns, in_aggregation_column, 
-                                                      out_groupby_columns, out_aggregation_column, sort_result);
-      }
-    default:
-     {
-       std::cout << "Unsupported groupby column type:" << groupby_column_type << std::endl;
-       return GDF_UNSUPPORTED_DTYPE;
-     }
-  }
-
-}
 
 /* --------------------------------------------------------------------------*/
 /** 

                            bool sort_result = false)
{

  // TODO Currently only supports a single groupby column
  if(ncols > 1) {
    std::cerr << "Can only support a single groupby column at this time.\n";
    return GDF_GROUPBY_TOO_MANY_COLUMNS;
  }

  return dispatch_groupby_type<aggregation_operation>(ncols, in_groupby_columns, in_aggregation_column, 
                                                      out_groupby_columns, out_aggregation_column, sort_result);
}

/* --------------------------------------------------------------------------*/

 * @Returns gdf_error
 */
/* ----------------------------------------------------------------------------*/
template <template <typename aggregation_type> class aggregation_operation,
          typename size_type>
gdf_error gdf_group_by_hash(size_type ncols,               
                            gdf_column* in_groupby_columns[],        
                            gdf_column* in_aggregation_column,       
                            gdf_column* out_groupby_columns[],
