Kinetica   C#   API  Version 7.2.3.1
AggregateTests.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using Xunit;
4 using Kinetica.Tests.Common;
5 using kinetica;
6 
8 {
13  [Trait("Category", "Integration")]
14  public class AggregateTests
15  {
19  private string SetupNumericTable(TestContext ctx, int numRecords)
20  {
21  var tableName = ctx.QualifiedTable("numeric_table");
22 
23  // Create table using SQL
24  ctx.Kinetica.executeSql($"CREATE TABLE {tableName} (id INT NOT NULL, value DOUBLE, category VARCHAR(16), score INT, PRIMARY KEY (id))");
25 
26  // Insert records with varying data
27  for (int i = 0; i < numRecords; i++)
28  {
29  var category = (i % 3) switch
30  {
31  0 => "A",
32  1 => "B",
33  _ => "C"
34  };
35  var value = i * 1.5;
36  var score = i % 10;
37  ctx.Kinetica.executeSql($"INSERT INTO {tableName} (id, value, category, score) VALUES ({i}, {value}, '{category}', {score})");
38  }
39 
40  return tableName;
41  }
42 
43  // ============================================================================
44  // AGGREGATE UNIQUE TESTS
45  // ============================================================================
46 
47  [Fact]
49  {
50  using var ctx = new TestContext("agg_unique_basic");
51  var tableName = SetupNumericTable(ctx, 30);
52 
53  // Get unique categories (should be A, B, C)
54  var resp = ctx.Kinetica.aggregateUnique(tableName, "category", 0, -9999, new Dictionary<string, string>());
55 
56  // Response has data as IList<KineticaRecord> - should have 3 unique categories
57  Assert.Equal(3, resp.data.Count);
58  }
59 
60  [Fact]
62  {
63  using var ctx = new TestContext("agg_unique_num");
64  var tableName = SetupNumericTable(ctx, 30);
65 
66  // Get unique scores (0-9, repeating pattern)
67  var resp = ctx.Kinetica.aggregateUnique(tableName, "score", 0, -9999, new Dictionary<string, string>());
68 
69  // Should have 10 unique scores (0-9)
70  Assert.Equal(10, resp.data.Count);
71  }
72 
73  [Fact]
75  {
76  using var ctx = new TestContext("agg_unique_limit");
77  var tableName = SetupNumericTable(ctx, 30);
78 
79  // Get unique categories with limit
80  var resp = ctx.Kinetica.aggregateUnique(tableName, "category", 0, 2, new Dictionary<string, string>());
81 
82  // Should be limited to 2
83  Assert.Equal(2, resp.data.Count);
84  }
85 
86  [Fact]
88  {
89  using var ctx = new TestContext("agg_unique_empty");
90  var tableName = SetupNumericTable(ctx, 0);
91 
92  var resp = ctx.Kinetica.aggregateUnique(tableName, "category", 0, -9999, new Dictionary<string, string>());
93 
94  // Empty table returns empty data
95  Assert.Empty(resp.data);
96  }
97 
98  // ============================================================================
99  // AGGREGATE MIN/MAX TESTS
100  // ============================================================================
101 
102  [Fact]
104  {
105  using var ctx = new TestContext("agg_minmax_basic");
106  var tableName = SetupNumericTable(ctx, 100);
107 
108  var resp = ctx.Kinetica.aggregateMinMax(tableName, "id", new Dictionary<string, string>());
109 
110  Assert.Equal(0.0, resp.min);
111  Assert.Equal(99.0, resp.max);
112  }
113 
114  [Fact]
116  {
117  using var ctx = new TestContext("agg_minmax_double");
118  var tableName = SetupNumericTable(ctx, 100);
119 
120  var resp = ctx.Kinetica.aggregateMinMax(tableName, "value", new Dictionary<string, string>());
121 
122  // value = id * 1.5, so min = 0.0, max = 99 * 1.5 = 148.5
123  Assert.Equal(0.0, resp.min);
124  Assert.Equal(148.5, resp.max);
125  }
126 
127  [Fact]
129  {
130  using var ctx = new TestContext("agg_minmax_single");
131  var tableName = SetupNumericTable(ctx, 1);
132 
133  var resp = ctx.Kinetica.aggregateMinMax(tableName, "id", new Dictionary<string, string>());
134 
135  Assert.Equal(0.0, resp.min);
136  Assert.Equal(0.0, resp.max);
137  }
138 
139  // ============================================================================
140  // AGGREGATE HISTOGRAM TESTS
141  // ============================================================================
142 
143  [Fact]
145  {
146  using var ctx = new TestContext("agg_hist_basic");
147  var tableName = SetupNumericTable(ctx, 100);
148 
149  // Create histogram with 10 bins over range 0-99
150  var resp = ctx.Kinetica.aggregateHistogram(tableName, "id", 0.0, 100.0, 10.0, new Dictionary<string, string>());
151 
152  Assert.Equal(10, resp.counts.Count); // Should have 10 bins
153  // Each bin should have approximately 10 values
154  foreach (var count in resp.counts)
155  {
156  Assert.True(count >= 9.0 && count <= 11.0); // Allow some tolerance
157  }
158  }
159 
160  [Fact]
162  {
163  using var ctx = new TestContext("agg_hist_uneven");
164  var tableName = SetupNumericTable(ctx, 50);
165 
166  // Create histogram on score column (values 0-9 repeating)
167  var resp = ctx.Kinetica.aggregateHistogram(tableName, "score", 0.0, 10.0, 2.0, new Dictionary<string, string>());
168 
169  Assert.Equal(5, resp.counts.Count); // Should have 5 bins
170  Assert.Equal(0.0, resp.start);
171  Assert.Equal(10.0, resp.end);
172  }
173 
174  [Fact]
176  {
177  using var ctx = new TestContext("agg_hist_empty");
178  var tableName = SetupNumericTable(ctx, 0);
179 
180  var resp = ctx.Kinetica.aggregateHistogram(tableName, "id", 0.0, 100.0, 10.0, new Dictionary<string, string>());
181 
182  // All bins should be empty
183  foreach (var count in resp.counts)
184  {
185  Assert.Equal(0.0, count);
186  }
187  }
188 
189  [Fact]
191  {
192  using var ctx = new TestContext("agg_hist_single");
193  var tableName = SetupNumericTable(ctx, 100);
194 
195  // Create histogram with single bin covering all data
196  var resp = ctx.Kinetica.aggregateHistogram(tableName, "id", 0.0, 100.0, 100.0, new Dictionary<string, string>());
197 
198  Assert.Single(resp.counts);
199  Assert.Equal(100.0, resp.counts[0]); // All records in one bin
200  }
201 
202  // ============================================================================
203  // AGGREGATE STATISTICS TESTS
204  // ============================================================================
205 
206  [Fact]
208  {
209  using var ctx = new TestContext("agg_stats_basic");
210  var tableName = SetupNumericTable(ctx, 100);
211 
212  var resp = ctx.Kinetica.aggregateStatistics(tableName, "id", "mean,stdv,count", new Dictionary<string, string>());
213 
214  // For 0-99: mean = 49.5, count = 100
215  Assert.True(Math.Abs(resp.stats["mean"] - 49.5) < 0.1);
216  Assert.Equal(100.0, resp.stats["count"]);
217  Assert.True(resp.stats.ContainsKey("stdv"));
218  }
219 
220  [Fact]
222  {
223  using var ctx = new TestContext("agg_stats_all");
224  var tableName = SetupNumericTable(ctx, 100);
225 
226  var resp = ctx.Kinetica.aggregateStatistics(tableName, "value", "mean,stdv,variance,skew,kurtosis,sum", new Dictionary<string, string>());
227 
228  Assert.True(resp.stats.ContainsKey("mean"));
229  Assert.True(resp.stats.ContainsKey("stdv"));
230  Assert.True(resp.stats.ContainsKey("variance"));
231  Assert.True(resp.stats.ContainsKey("sum"));
232  }
233 
234  [Fact]
236  {
237  using var ctx = new TestContext("agg_stats_empty");
238  var tableName = SetupNumericTable(ctx, 0);
239 
240  var resp = ctx.Kinetica.aggregateStatistics(tableName, "id", "mean,count", new Dictionary<string, string>());
241 
242  Assert.Equal(0.0, resp.stats["count"]);
243  }
244 
245  // ============================================================================
246  // AGGREGATE GROUP BY TESTS
247  // ============================================================================
248 
249  [Fact]
251  {
252  using var ctx = new TestContext("agg_groupby_count");
253  var tableName = SetupNumericTable(ctx, 30);
254 
255  // Group by category and count
256  var resp = ctx.Kinetica.aggregateGroupBy(tableName, new List<string> { "category" }, 0, -9999, new Dictionary<string, string>());
257 
258  // Should have 3 groups (A, B, C)
259  Assert.Equal(3, resp.total_number_of_records);
260  Assert.Equal(3, resp.data.Count);
261  }
262 
263  [Fact]
265  {
266  using var ctx = new TestContext("agg_groupby_agg");
267  var tableName = SetupNumericTable(ctx, 30);
268 
269  // Group by category
270  var resp = ctx.Kinetica.aggregateGroupBy(tableName, new List<string> { "category" }, 0, -9999, new Dictionary<string, string>());
271 
272  // 3 categories
273  Assert.Equal(3, resp.data.Count);
274  }
275 
276  [Fact]
278  {
279  using var ctx = new TestContext("agg_groupby_multi");
280 
281  // Create table with more grouping dimensions
282  var tableName = ctx.QualifiedTable("multi_group_table");
283  ctx.Kinetica.executeSql($"CREATE TABLE {tableName} (id INT NOT NULL, cat1 VARCHAR(16), cat2 VARCHAR(16), value DOUBLE, PRIMARY KEY (id))");
284 
285  // Insert test data
286  for (int i = 0; i < 20; i++)
287  {
288  var cat1 = i < 10 ? "X" : "Y";
289  var cat2 = (i % 2) == 0 ? "P" : "Q";
290  ctx.Kinetica.executeSql($"INSERT INTO {tableName} (id, cat1, cat2, value) VALUES ({i}, '{cat1}', '{cat2}', {(double)i})");
291  }
292 
293  // Group by both columns
294  var resp = ctx.Kinetica.aggregateGroupBy(tableName, new List<string> { "cat1", "cat2" }, 0, -9999, new Dictionary<string, string>());
295 
296  // Should have 4 groups: (X,P), (X,Q), (Y,P), (Y,Q)
297  Assert.Equal(4, resp.data.Count);
298  }
299 
300  [Fact]
302  {
303  using var ctx = new TestContext("agg_groupby_empty");
304  var tableName = SetupNumericTable(ctx, 0);
305 
306  var resp = ctx.Kinetica.aggregateGroupBy(tableName, new List<string> { "category" }, 0, -9999, new Dictionary<string, string>());
307 
308  // Empty table returns empty data
309  Assert.Empty(resp.data);
310  }
311 
312  [Fact]
314  {
315  using var ctx = new TestContext("agg_groupby_limit");
316  var tableName = SetupNumericTable(ctx, 30);
317 
318  // Group by category with limit
319  var resp = ctx.Kinetica.aggregateGroupBy(tableName, new List<string> { "category" }, 0, 2, new Dictionary<string, string>());
320 
321  // Limited to 2 groups
322  Assert.Equal(2, resp.data.Count);
323  }
324  }
325 }
ExecuteSqlResponse executeSql(ExecuteSqlRequest request_)
Execute a SQL statement (query, DML, or DDL).
Test context that manages schema and cleanup for integration tests.
Definition: TestContext.cs:11
string QualifiedTable(string tableName)
Get a qualified table name (schema.table).
Definition: TestContext.cs:74