diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31b7a9d9b04b1ef04b5d04ac5565de1aa9bfd204..081ca7101bd9da734ee75044045ff4fd6f1a136c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added
 
+- Add `least()` functions on `MagicDotPath`
 - Add `greatest()` functions on `MagicDotPath`
 
 ## [1.10.0-pre-release] - 2023-15-12
diff --git a/docs/doc/examples/functions.md b/docs/doc/examples/functions.md
index fa96ecfb1633973667c02c0a57ff22cda20a3bc7..bda866de5090970e6f8aa58d3876257783a0335a 100644
--- a/docs/doc/examples/functions.md
+++ b/docs/doc/examples/functions.md
@@ -27,6 +27,7 @@ removing trailing zeroes.
   - **trunc(v)**: Truncates to integer (towards zero).
   - **trunc(v, s)**: Truncates v to s decimal places.
 - **greatest**: Returns the largest of the values.
+- **least**: Returns the smallest of the values.
 
 ## Trigonometric functions
 
diff --git a/py_linq_sql/__init__.py b/py_linq_sql/__init__.py
index 025411c260e5ca43309b78965ac3cb12435618d5..ffd64aa4eebf8440a43eb9fbd1b698a88d6eb4ca 100644
--- a/py_linq_sql/__init__.py
+++ b/py_linq_sql/__init__.py
@@ -70,6 +70,7 @@ from .utils.functions.magic_dp_maths_functions import (  # noqa: F401
     gcd,
     greatest,
     lcm,
+    least,
     ln,
     log,
     log10,
diff --git a/py_linq_sql/utils/classes/op_and_func_of_mdp.py b/py_linq_sql/utils/classes/op_and_func_of_mdp.py
index a40a8b3e3598eb1c78b4885db2996834bec4ac79..1212c7132f4db6a6a4a795516808bdabc6b52516 100644
--- a/py_linq_sql/utils/classes/op_and_func_of_mdp.py
+++ b/py_linq_sql/utils/classes/op_and_func_of_mdp.py
@@ -69,6 +69,7 @@ class MathFunctType(_MathFunction, Enum):
     TRIM_SCALE = _MathFunction(python=None, psql="trim_scale", name="trimScale")
     TRUNC = _MathFunction(python="trunc", psql="trunc", name="trunc")
     GREATEST = _MathFunction(python="max", psql="greatest", name="greatest")
+    LEAST = _MathFunction(python="min", psql="least", name="least")
 
 
 class OperatorType(_Operator, Enum):
@@ -177,6 +178,7 @@ def col_name_math(name_op: DotMap, operator: _OPERATORTYPE) -> str:
         MathFunctType.ROUND,
         MathFunctType.TRUNC,
         MathFunctType.GREATEST,
+        MathFunctType.LEAST,
     ]:
         return f"{operator.name}_{name_op.op1}_{name_op.op2}"
 
@@ -323,7 +325,7 @@ def json_path_math(path_op: DotMap, operator: _OPERATORTYPE) -> str:
     if operator in [MathFunctType.LOG]:
         return f"{operator.psql}({path_op.op2}, CAST({path_op.op1} AS decimal))"
 
-    if operator in [MathFunctType.GREATEST]:
+    if operator in [MathFunctType.GREATEST, MathFunctType.LEAST]:
         operand_1 = f"CAST({path_op.op1} AS decimal)"
         operand_2 = f"CAST({path_op.op2} AS decimal)"
         return f"{operator.psql}({operand_1}, {operand_2})"
diff --git a/py_linq_sql/utils/functions/magic_dp_maths_functions.py b/py_linq_sql/utils/functions/magic_dp_maths_functions.py
index c5a36ced4e17f4aa826ae1a2a2fc55cc229acef0..a10648f8eac92767562e1b3c5b8cdc197fa575e7 100644
--- a/py_linq_sql/utils/functions/magic_dp_maths_functions.py
+++ b/py_linq_sql/utils/functions/magic_dp_maths_functions.py
@@ -461,3 +461,37 @@ def greatest(
         other,
         MathFunctType.GREATEST,
     )
+
+
+# TODO: add support for more than 2 operands
+# TODO: add support for only one operand
+def least(
+    mdp: BaseMagicDotPath, other: _NUMBER_TYPE | BaseMagicDotPath
+) -> MagicDotPathWithOp:
+    """
+    Greatest function for a MagicDotPath.
+
+    This is equivalent to the `min` function in python.
+
+    From psql docs: The LEAST function select the smallest value from a list of any
+    number of expressions. The expressions must all be convertible to a common data
+    type, which will be the type of the result
+
+    See:
+    https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST
+
+    Args:
+        mdp: MagicDotPath on which we apply the least.
+        other: An other element for
+            the comparison.
+
+    Returns:
+        MagicDotPathWithOp with 2 operand and on the correct operator.
+
+    Raises:
+        TypeOperatorError: Indirect raise by `BaseMagicDotPath._get_number_operator`
+    """
+    return mdp._get_number_operator(  # pylint: disable=protected-access
+        other,
+        MathFunctType.LEAST,
+    )
diff --git a/tests/operators/test_more_math_op.py b/tests/operators/test_more_math_op.py
index 7ed969754163903ade6ad286b57fa9ac8427b3e0..6c1c0e74b301caa1e315b57ff79def1a1ebb4f37 100644
--- a/tests/operators/test_more_math_op.py
+++ b/tests/operators/test_more_math_op.py
@@ -30,6 +30,7 @@ from py_linq_sql import floor as floor_sql
 from py_linq_sql import gcd as gcd_sql
 from py_linq_sql import greatest as greatest_sql
 from py_linq_sql import lcm as lcm_sql
+from py_linq_sql import least as least_sql
 from py_linq_sql import ln as ln_sql
 from py_linq_sql import log as log_sql
 from py_linq_sql import log10 as log10_sql
@@ -791,3 +792,76 @@ def test_math_function_greatest(
     x.data.mass = input_mass
 
     assert_that(val).is_equal_to(input_lambda(max, x))
+
+
+@pytest.mark.parametrize(
+    "input_mass, input_lambda",
+    [
+        param(
+            23,
+            lambda least, x: least(x.data.mass, 51),
+            id="least_left_positive",
+        ),
+        param(
+            51,
+            lambda least, x: least(x.data.mass, 23),
+            id="least_right_positive",
+        ),
+        param(
+            -123,
+            lambda least, x: least(x.data.mass, -18),
+            id="least_left_negative",
+        ),
+        param(
+            -18,
+            lambda least, x: least(x.data.mass, -123),
+            id="least_right_negative",
+        ),
+        param(
+            -16,
+            lambda least, x: least(x.data.mass, 18),
+            id="least_left_negpos",
+        ),
+        param(
+            16,
+            lambda least, x: least(x.data.mass, -18),
+            id="least_right_negpos",
+        ),
+        param(0, lambda least, x: least(x.data.mass, 43), id="least_left_zero"),
+        param(43, lambda least, x: least(x.data.mass, 0), id="least_right_zero"),
+        param(17, lambda least, x: least(x.data.mass, 17), id="least_left_equal"),
+        param(
+            0, lambda least, x: least(x.data.mass, -43), id="least_left_zero_right_neg"
+        ),
+        param(
+            -43, lambda least, x: least(x.data.mass, 0), id="least_right_zero_left_neg"
+        ),
+        param(
+            15,
+            lambda least, x: least(x.data.mass, x.data.mass),
+            id="least_mass_mass",
+        ),
+    ],
+)
+def test_math_function_least(
+    db_connection_with_only_schema_for_modif,
+    table_objects,
+    input_mass,
+    input_lambda,
+):
+    insert_value(
+        db_connection_with_only_schema_for_modif, {"name": "test", "mass": input_mass}
+    )
+
+    fquery_least = partial(input_lambda, least_sql)
+
+    val = (
+        SQLEnumerable(db_connection_with_only_schema_for_modif, table_objects)
+        .select(fquery_least)
+        .execute()
+    ).to_list()[0][0]
+
+    x = DotMap()
+    x.data.mass = input_mass
+
+    assert_that(val).is_equal_to(input_lambda(min, x))
diff --git a/tests/operators/test_name_w_op.py b/tests/operators/test_name_w_op.py
index edb1c8c787aebe7bca3d9049fa743e8ac5ddf786..c2b10712d56d5f848fd7c3d07e84a43dd6812813 100644
--- a/tests/operators/test_name_w_op.py
+++ b/tests/operators/test_name_w_op.py
@@ -69,6 +69,12 @@ def test_col_name_hyperB(input_operator, input_expected):
             "greatest_mass_number",
             id="greatest_col_name",
         ),
+        param(
+            MathFunctType.LEAST,
+            DotMap(op1="mass", op2="number"),
+            "least_mass_number",
+            id="least_col_name",
+        ),
         param(
             MathFunctType.LCM,
             DotMap(op1="mass", op2="number"),