Skip to content

Commit a18729b

Browse files
committed
Fix grouped count aggregation on SQL Server
1 parent 5122d43 commit a18729b

2 files changed

Lines changed: 46 additions & 4 deletions

File tree

‎QueryBuilder.Tests/AggregateTests.cs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ public void CountMultipleColumns()
2929
Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT 1 FROM [A] WHERE [ColumnA] IS NOT NULL AND [ColumnB] IS NOT NULL) AS [countQuery]", c[EngineCodes.SqlServer]);
3030
}
3131

32+
[Fact]
33+
public void CountWithGroupBy()
34+
{
35+
var query = new Query("org_storage")
36+
.Select("organization_id")
37+
.LeftJoin("organizations", "org_storage.organization_id", "organizations.id")
38+
.GroupBy("organization_id")
39+
.AsCount();
40+
41+
var c = Compile(query);
42+
43+
Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT [organization_id] FROM [org_storage] \nLEFT JOIN [organizations] ON [org_storage].[organization_id] = [organizations].[id] GROUP BY [organization_id]) AS [countQuery]", c[EngineCodes.SqlServer]);
44+
}
45+
3246
[Fact]
3347
public void DistinctCount()
3448
{
@@ -69,6 +83,18 @@ public void Sum()
6983
Assert.Equal("SELECT SUM([PacketsDropped]) AS [sum] FROM [A]", c[EngineCodes.SqlServer]);
7084
}
7185

86+
[Fact]
87+
public void SumWithGroupBy()
88+
{
89+
var query = new Query("A")
90+
.GroupBy("UserId")
91+
.AsSum("PacketsDropped");
92+
93+
var c = Compile(query);
94+
95+
Assert.Equal("SELECT SUM([PacketsDropped]) AS [sum] FROM [A] GROUP BY [UserId]", c[EngineCodes.SqlServer]);
96+
}
97+
7298
[Fact]
7399
public void Max()
74100
{

‎QueryBuilder/Compilers/Compiler.cs‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,33 @@ protected SqlResult PrepareResult(SqlResult ctx)
8080
private Query TransformAggregateQuery(Query query)
8181
{
8282
var clause = query.GetOneComponent<AggregateClause>("aggregate", EngineCode);
83+
var hasGroup = query.HasComponent("group", EngineCode);
8384

84-
if (clause.Columns.Count == 1 && !query.IsDistinct) return query;
85+
if (clause.Columns.Count == 1 && !query.IsDistinct && (!hasGroup || clause.Type != "count")) return query;
86+
87+
if (hasGroup && clause.Columns.Count == 1 && !query.IsDistinct)
88+
{
89+
var innerQuery = query.Clone();
90+
innerQuery.ClearComponent("aggregate", EngineCode);
91+
92+
var groupedOuterClause = new AggregateClause()
93+
{
94+
Columns = new List<string> { "*" },
95+
Type = clause.Type
96+
};
97+
98+
return new Query()
99+
.AddComponent("aggregate", groupedOuterClause)
100+
.From(innerQuery, $"{clause.Type}Query");
101+
}
85102

86103
if (query.IsDistinct)
87104
{
88105
query.ClearComponent("aggregate", EngineCode);
89106
query.ClearComponent("select", EngineCode);
90107
query.Select(clause.Columns.ToArray());
91108
}
92-
else
109+
else if (!hasGroup)
93110
{
94111
foreach (var column in clause.Columns)
95112
{
@@ -129,8 +146,7 @@ protected virtual SqlResult CompileRaw(Query query)
129146
if (query.Method == "aggregate")
130147
{
131148
query.ClearComponent("limit")
132-
.ClearComponent("order")
133-
.ClearComponent("group");
149+
.ClearComponent("order");
134150

135151
query = TransformAggregateQuery(query);
136152
}

0 commit comments

Comments
 (0)