diff --git a/src/Driver/Test/TestTableEntryGroup.php b/src/Driver/Test/TestTableEntryGroup.php index b65add4..d0f1764 100644 --- a/src/Driver/Test/TestTableEntryGroup.php +++ b/src/Driver/Test/TestTableEntryGroup.php @@ -110,6 +110,10 @@ public function aggregateAndAlias(?array $fields, bool $collapse = true): static } elseif ($field->function === SelectField::AVERAGE) { $averageFields[$key]++; $aggregatedEntry[$key] += $entry[$field->key] ?? 0; + } elseif ($field->function === SelectField::MIN) { + $aggregatedEntry[$key] = min($aggregatedEntry[$key] ?? PHP_INT_MAX, $entry[$field->key] ?? PHP_INT_MAX); + } elseif ($field->function === SelectField::MAX) { + $aggregatedEntry[$key] = max($aggregatedEntry[$key] ?? PHP_INT_MIN, $entry[$field->key] ?? PHP_INT_MIN); } } } @@ -135,4 +139,4 @@ public function aggregateAndAlias(?array $fields, bool $collapse = true): static return $this; } -} \ No newline at end of file +} diff --git a/src/Query/Generator/SQL.php b/src/Query/Generator/SQL.php index 89cc6f6..5a57cdf 100644 --- a/src/Query/Generator/SQL.php +++ b/src/Query/Generator/SQL.php @@ -217,6 +217,12 @@ private function generateFields(Query $query): string case SelectField::AVERAGE: $fieldString .= "AVG("; break; + case SelectField::MIN: + $fieldString .= "MIN("; + break; + case SelectField::MAX: + $fieldString .= "MAX("; + break; } } @@ -290,4 +296,4 @@ private function generateValue(float|int|string|null|array $value): string return $this->stringEnclosure . $value . $this->stringEnclosure; } -} \ No newline at end of file +} diff --git a/src/Query/MaxField.php b/src/Query/MaxField.php new file mode 100644 index 0000000..91979c1 --- /dev/null +++ b/src/Query/MaxField.php @@ -0,0 +1,29 @@ +setAlias($key); + } + + /** + * @param string|null $key + * @return static + */ + public function setKey(?string $key): static + { + $this->setAlias($key); + return parent::setKey($key); + } +} diff --git a/src/Query/MinField.php b/src/Query/MinField.php new file mode 100644 index 0000000..de9b472 --- /dev/null +++ b/src/Query/MinField.php @@ -0,0 +1,29 @@ +setAlias($key); + } + + /** + * @param string|null $key + * @return static + */ + public function setKey(?string $key): static + { + $this->setAlias($key); + return parent::setKey($key); + } +} diff --git a/src/Query/SelectField.php b/src/Query/SelectField.php index 75c99e4..1ddff9a 100644 --- a/src/Query/SelectField.php +++ b/src/Query/SelectField.php @@ -9,9 +9,11 @@ */ class SelectField extends Field { - const COUNT = 0, + const int COUNT = 0, SUM = 1, - AVERAGE = 2; + AVERAGE = 2, + MIN = 3, + MAX = 4; /** * @var string|null @@ -57,4 +59,4 @@ public function setRaw(bool $raw = true): SelectField $this->raw = $raw; return $this; } -} \ No newline at end of file +} diff --git a/test/tests/SQLTest.php b/test/tests/SQLTest.php index fa3cfc9..647b627 100644 --- a/test/tests/SQLTest.php +++ b/test/tests/SQLTest.php @@ -226,6 +226,46 @@ public function testSelectAVG() $this->assertEquals("SELECT AVG(`number`) FROM `test`", $this->sql->generate($query)); } + public function testSelectMin() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::MIN), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT MIN(`number`) FROM `test`", $this->sql->generate($query)); + } + + public function testSelectMinAs() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::MIN)->setAlias('minNumber'), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT MIN(`number`) AS `minNumber` FROM `test`", $this->sql->generate($query)); + } + + public function testSelectMax() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::MAX), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT MAX(`number`) FROM `test`", $this->sql->generate($query)); + } + + public function testSelectMaxAs() + { + $query = new SelectQuery(fields: [ + (new SelectField('number'))->setFunction(SelectField::MAX)->setAlias('maxNumber'), + ]); + $query->modelClassName = TestModel::class; + + $this->assertEquals("SELECT MAX(`number`) AS `maxNumber` FROM `test`", $this->sql->generate($query)); + } + public function testSelectLimitNumber() { $query = new SelectQuery(limit:100); diff --git a/test/tests/TestDriverTest.php b/test/tests/TestDriverTest.php index d3712ab..a09cd5c 100644 --- a/test/tests/TestDriverTest.php +++ b/test/tests/TestDriverTest.php @@ -6,6 +6,8 @@ use Aternos\Model\Driver\Test\TestDriver; use Aternos\Model\Query\CountField; use Aternos\Model\Query\DeleteQuery; +use Aternos\Model\Query\MaxField; +use Aternos\Model\Query\MinField; use Aternos\Model\Query\OrderField; use Aternos\Model\Query\SelectField; use Aternos\Model\Query\SumField; @@ -496,6 +498,56 @@ public function testSelectGroupAverage(): void } } + public function testSelectGroupMin(): void + { + $model = new TestModel(); + $model->id = "-5A"; + $model->text = "A"; + $model->number = -5; + $model->save(); + + $models = TestModel::select(fields: [ + new MinField("number"), + new SelectField("number"), + new SelectField("text"), + ], group: ["text"]); + + $this->assertTrue($models->wasSuccessful()); + $this->assertCount(10, $models); + foreach ($models as $model) { + if ($model->text === "A") { + $this->assertEquals(-5, $model->getField("number")); + } else { + $this->assertEquals($model->number, $model->getField("number")); + } + } + } + + public function testSelectGroupMax(): void + { + $model = new TestModel(); + $model->id = "5A"; + $model->text = "A"; + $model->number = 5; + $model->save(); + + $models = TestModel::select(fields: [ + new MaxField("number"), + new SelectField("number"), + new SelectField("text"), + ], group: ["text"]); + + $this->assertTrue($models->wasSuccessful()); + $this->assertCount(10, $models); + foreach ($models as $model) { + if ($model->text === "A") { + $this->assertEquals(5, $model->getField("number")); + } else { + $this->assertEquals($model->number, $model->getField("number")); + } + } + } + /** * @return void * @throws Exception @@ -554,4 +606,4 @@ protected function tearDown(): void { TestModel::clearTestEntries(); } -} \ No newline at end of file +}