You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2023/03/16 10:29:30 UTC

[iotdb] branch master updated: [IoTDB-5636] Add round as built-in scalar function

This is an automated email from the ASF dual-hosted git repository.

jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 53d06b296b [IoTDB-5636] Add round as built-in scalar function
53d06b296b is described below

commit 53d06b296b272902de1194e2c6856220665a5f01
Author: Zhijia Cao <ca...@126.com>
AuthorDate: Thu Mar 16 18:29:21 2023 +0800

    [IoTDB-5636] Add round as built-in scalar function
---
 .../org/apache/iotdb/db/qp/sql/IdentifierParser.g4 |   1 +
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |   1 +
 .../antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4  |   4 +
 docs/UserGuide/Operators-Functions/Mathematical.md |  65 ++--
 .../UserGuide/Operators-Functions/Mathematical.md  |  63 ++--
 docs/zh/UserGuide/Operators-Functions/Overview.md  |  44 +--
 .../itbase/constant/BuiltinScalarFunctionEnum.java |   1 +
 .../BuiltinTimeSeriesGeneratingFunctionEnum.java   |   1 -
 .../scalar/IoTDBRoundFunctionIT.java               | 327 +++++++++++++++++++++
 .../commons/udf/builtin/BuiltinScalarFunction.java |   1 +
 .../BuiltinTimeSeriesGeneratingFunction.java       |   1 -
 .../iotdb/commons/udf/builtin/UDTFRound.java       |  28 --
 .../org/apache/iotdb/db/constant/SqlConstant.java  |   2 +
 .../plan/expression/multi/FunctionExpression.java  |   2 +-
 .../multi/builtin/BuiltInScalarFunctionHelper.java |   4 +-
 .../BuiltInScalarFunctionHelperFactory.java        |   3 +
 .../multi/builtin/helper/RoundFunctionHelper.java  |  84 ++++++
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |  14 +
 .../scalar/RoundFunctionColumnTransformer.java     |  72 +++++
 .../unary/scalar/RoundFunctionTransformer.java     |  72 +++++
 20 files changed, 691 insertions(+), 99 deletions(-)

diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
index 3ebcd8f92d..ce0b227f43 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
@@ -156,6 +156,7 @@ keyWords
     | REPLACE
     | REVOKE
     | ROLE
+    | ROUND
     | RUNNING
     | SCHEMA
     | SELECT
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index b5173fe252..e7a8e8b603 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -983,6 +983,7 @@ functionName
 scalarFunctionExpression
     : CAST LR_BRACKET castInput=expression AS attributeValue RR_BRACKET
     | REPLACE LR_BRACKET text=expression COMMA from=STRING_LITERAL COMMA to=STRING_LITERAL RR_BRACKET
+    | ROUND LR_BRACKET input=expression (COMMA places=constant)? RR_BRACKET
     ;
 
 
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
index 3791743780..9e5bfcf417 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
@@ -570,6 +570,10 @@ ROOT
     : R O O T
     ;
 
+ROUND
+    : R O U N D
+    ;
+
 RUNNING
     : R U N N I N G
     ;
diff --git a/docs/UserGuide/Operators-Functions/Mathematical.md b/docs/UserGuide/Operators-Functions/Mathematical.md
index f477e58c83..c5e2146404 100644
--- a/docs/UserGuide/Operators-Functions/Mathematical.md
+++ b/docs/UserGuide/Operators-Functions/Mathematical.md
@@ -67,28 +67,28 @@ It costs 0.014s
 
 Currently, IoTDB supports the following mathematical functions. The behavior of these mathematical functions is consistent with the behavior of these functions in the Java Math standard library.
 
-| Function Name | Allowed Input Series Data Types | Output Series Data Type       | Corresponding Implementation in the Java Standard Library    |
-| ------------- | ------------------------------- | ----------------------------- | ------------------------------------------------------------ |
-| SIN           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#sin(double)                                             |
-| COS           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#cos(double)                                             |
-| TAN           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#tan(double)                                             |
-| ASIN          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#asin(double)                                            |
-| ACOS          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#acos(double)                                            |
-| ATAN          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#atan(double)                                            |
-| SINH          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#sinh(double)                                            |
-| COSH          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#cosh(double)                                            |
-| TANH          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#tanh(double)                                            |
-| DEGREES       | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#toDegrees(double)                                       |
-| RADIANS       | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#toRadians(double)                                       |
-| ABS           | INT32 / INT64 / FLOAT / DOUBLE  | Same type as the input series | Math#abs(int) / Math#abs(long) /Math#abs(float) /Math#abs(double) |
-| SIGN          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#signum(double)                                          |
-| CEIL          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#ceil(double)                                            |
-| FLOOR         | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#floor(double)                                           |
-| ROUND         | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#rint(double)                                            |
-| EXP           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#exp(double)                                             |
-| LN            | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#log(double)                                             |
-| LOG10         | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#log10(double)                                           |
-| SQRT          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        | Math#sqrt(double)                                            |
+| Function Name | Allowed Input Series Data Types | Output Series Data Type       |Necessary attribute parameter     | Corresponding Implementation in the Java Standard Library    |
+| ------------- | ------------------------------- | ----------------------------- |-----| ------------------------------------------------------------ |
+| SIN           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#sin(double)                                             |
+| COS           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#cos(double)                                             |
+| TAN           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#tan(double)                                             |
+| ASIN          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#asin(double)                                            |
+| ACOS          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#acos(double)                                            |
+| ATAN          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#atan(double)                                            |
+| SINH          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#sinh(double)                                            |
+| COSH          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#cosh(double)                                            |
+| TANH          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#tanh(double)                                            |
+| DEGREES       | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#toDegrees(double)                                       |
+| RADIANS       | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#toRadians(double)                                       |
+| ABS           | INT32 / INT64 / FLOAT / DOUBLE  | Same type as the input series |     | Math#abs(int) / Math#abs(long) /Math#abs(float) /Math#abs(double) |
+| SIGN          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#signum(double)                                          |
+| CEIL          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#ceil(double)                                            |
+| FLOOR         | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#floor(double)                                           |
+| ROUND         | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |'places' : Round the significant number, positive number is the significant number after the decimal point, negative number is the significant number of whole number     | Math#rint(Math#pow(10,places))/Math#pow(10,places)                                            |
+| EXP           | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#exp(double)                                             |
+| LN            | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#log(double)                                             |
+| LOG10         | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#log10(double)                                           |
+| SQRT          | INT32 / INT64 / FLOAT / DOUBLE  | DOUBLE                        |     | Math#sqrt(double)                                            |
 
 Example:
 
@@ -110,4 +110,25 @@ Result:
 +-----------------------------+-------------------+-------------------+--------------------+-------------------+
 Total line number = 5
 It costs 0.008s
+```
+
+### ROUND
+Example:
+```sql
+select s4,round(s4),round(s4,2),round(s4,-1) from root.sg1.d1 
+```
+
+```sql
++-----------------------------+-------------+--------------------+----------------------+-----------------------+
+|                         Time|root.db.d1.s4|ROUND(root.db.d1.s4)|ROUND(root.db.d1.s4,2)|ROUND(root.db.d1.s4,-1)|
++-----------------------------+-------------+--------------------+----------------------+-----------------------+
+|1970-01-01T08:00:00.001+08:00|    101.14345|               101.0|                101.14|                  100.0|
+|1970-01-01T08:00:00.002+08:00|    20.144346|                20.0|                 20.14|                   20.0|
+|1970-01-01T08:00:00.003+08:00|    20.614372|                21.0|                 20.61|                   20.0|
+|1970-01-01T08:00:00.005+08:00|    20.814346|                21.0|                 20.81|                   20.0|
+|1970-01-01T08:00:00.006+08:00|     60.71443|                61.0|                 60.71|                   60.0|
+|2023-03-13T16:16:19.764+08:00|    10.143425|                10.0|                 10.14|                   10.0|
++-----------------------------+-------------+--------------------+----------------------+-----------------------+
+Total line number = 6
+It costs 0.059s
 ```
\ No newline at end of file
diff --git a/docs/zh/UserGuide/Operators-Functions/Mathematical.md b/docs/zh/UserGuide/Operators-Functions/Mathematical.md
index 9d96c440e6..3b5cf35c6c 100644
--- a/docs/zh/UserGuide/Operators-Functions/Mathematical.md
+++ b/docs/zh/UserGuide/Operators-Functions/Mathematical.md
@@ -69,28 +69,28 @@ It costs 0.014s
 
 目前 IoTDB 支持下列数学函数,这些数学函数的行为与这些函数在 Java Math 标准库中对应实现的行为一致。
 
-| 函数名  | 输入序列类型                   | 输出序列类型             | Java 标准库中的对应实现                                      |
-| ------- | ------------------------------ | ------------------------ | ------------------------------------------------------------ |
-| SIN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#sin(double)                                             |
-| COS     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#cos(double)                                             |
-| TAN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#tan(double)                                             |
-| ASIN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#asin(double)                                            |
-| ACOS    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#acos(double)                                            |
-| ATAN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#atan(double)                                            |
-| SINH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#sinh(double)                                            |
-| COSH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#cosh(double)                                            |
-| TANH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#tanh(double)                                            |
-| DEGREES | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#toDegrees(double)                                       |
-| RADIANS | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#toRadians(double)                                       |
-| ABS     | INT32 / INT64 / FLOAT / DOUBLE | 与输入序列的实际类型一致 | Math#abs(int) / Math#abs(long) /Math#abs(float) /Math#abs(double) |
-| SIGN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#signum(double)                                          |
-| CEIL    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#ceil(double)                                            |
-| FLOOR   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#floor(double)                                           |
-| ROUND   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#rint(double)                                            |
-| EXP     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#exp(double)                                             |
-| LN      | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#log(double)                                             |
-| LOG10   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#log10(double)                                           |
-| SQRT    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#sqrt(double)                                            |
+| 函数名  | 输入序列类型                   | 输出序列类型             | 必要属性参数    | Java 标准库中的对应实现                                      |
+| ------- | ------------------------------ | ------------------------ |-----------| ------------------------------------------------------------ |
+| SIN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#sin(double)                                             |
+| COS     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#cos(double)                                             |
+| TAN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#tan(double)                                             |
+| ASIN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#asin(double)                                            |
+| ACOS    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#acos(double)                                            |
+| ATAN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#atan(double)                                            |
+| SINH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#sinh(double)                                            |
+| COSH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#cosh(double)                                            |
+| TANH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#tanh(double)                                            |
+| DEGREES | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#toDegrees(double)                                       |
+| RADIANS | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#toRadians(double)                                       |
+| ABS     | INT32 / INT64 / FLOAT / DOUBLE | 与输入序列的实际类型一致 |           | Math#abs(int) / Math#abs(long) /Math#abs(float) /Math#abs(double) |
+| SIGN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#signum(double)                                          |
+| CEIL    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#ceil(double)                                            |
+| FLOOR   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#floor(double)                                           |
+| ROUND   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |`places`:四舍五入有效位数,正数为小数点后面的有效位数,负数为整数位的有效位数 | Math#rint(Math#pow(10,places))/Math#pow(10,places)|
+| EXP     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#exp(double)                                             |
+| LN      | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#log(double)                                             |
+| LOG10   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#log10(double)                                           |
+| SQRT    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |           | Math#sqrt(double)                                            |
 
 例如:
 
@@ -113,4 +113,23 @@ select s1, sin(s1), cos(s1), tan(s1) from root.sg1.d1 limit 5 offset 1000;
 Total line number = 5
 It costs 0.008s
 ```
+#### ROUND
+例如:
+```sql
+select s4,round(s4),round(s4,2),round(s4,-1) from root.sg1.d1 
+```
 
+```sql
++-----------------------------+-------------+--------------------+----------------------+-----------------------+
+|                         Time|root.db.d1.s4|ROUND(root.db.d1.s4)|ROUND(root.db.d1.s4,2)|ROUND(root.db.d1.s4,-1)|
++-----------------------------+-------------+--------------------+----------------------+-----------------------+
+|1970-01-01T08:00:00.001+08:00|    101.14345|               101.0|                101.14|                  100.0|
+|1970-01-01T08:00:00.002+08:00|    20.144346|                20.0|                 20.14|                   20.0|
+|1970-01-01T08:00:00.003+08:00|    20.614372|                21.0|                 20.61|                   20.0|
+|1970-01-01T08:00:00.005+08:00|    20.814346|                21.0|                 20.81|                   20.0|
+|1970-01-01T08:00:00.006+08:00|     60.71443|                61.0|                 60.71|                   60.0|
+|2023-03-13T16:16:19.764+08:00|    10.143425|                10.0|                 10.14|                   10.0|
++-----------------------------+-------------+--------------------+----------------------+-----------------------+
+Total line number = 6
+It costs 0.059s
+```
diff --git a/docs/zh/UserGuide/Operators-Functions/Overview.md b/docs/zh/UserGuide/Operators-Functions/Overview.md
index a57117cf2c..be0b9ff3f9 100644
--- a/docs/zh/UserGuide/Operators-Functions/Overview.md
+++ b/docs/zh/UserGuide/Operators-Functions/Overview.md
@@ -112,28 +112,28 @@ OR, |, ||
 
 ### 数学函数 
 
-| 函数名  | 输入序列类型                   | 输出序列类型             | Java 标准库中的对应实现                                      |
-| ------- | ------------------------------ | ------------------------ | ------------------------------------------------------------ |
-| SIN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#sin(double)                                             |
-| COS     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#cos(double)                                             |
-| TAN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#tan(double)                                             |
-| ASIN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#asin(double)                                            |
-| ACOS    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#acos(double)                                            |
-| ATAN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#atan(double)                                            |
-| SINH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#sinh(double)                                            |
-| COSH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#cosh(double)                                            |
-| TANH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#tanh(double)                                            |
-| DEGREES | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#toDegrees(double)                                       |
-| RADIANS | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#toRadians(double)                                       |
-| ABS     | INT32 / INT64 / FLOAT / DOUBLE | 与输入序列的实际类型一致 | Math#abs(int) / Math#abs(long) /Math#abs(float) /Math#abs(double) |
-| SIGN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#signum(double)                                          |
-| CEIL    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#ceil(double)                                            |
-| FLOOR   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#floor(double)                                           |
-| ROUND   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#rint(double)                                            |
-| EXP     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#exp(double)                                             |
-| LN      | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#log(double)                                             |
-| LOG10   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#log10(double)                                           |
-| SQRT    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | Math#sqrt(double)                                            |
+| 函数名  | 输入序列类型                   | 输出序列类型             | 必要属性参数                                       | Java 标准库中的对应实现                                                    |
+| ------- | ------------------------------ | ------------------------ |----------------------------------------------|-------------------------------------------------------------------|
+| SIN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#sin(double)                                                  |
+| COS     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#cos(double)                                                  |
+| TAN     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#tan(double)                                                  |
+| ASIN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#asin(double)                                                 |
+| ACOS    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#acos(double)                                                 |
+| ATAN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#atan(double)                                                 |
+| SINH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#sinh(double)                                                 |
+| COSH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#cosh(double)                                                 |
+| TANH    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#tanh(double)                                                 |
+| DEGREES | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#toDegrees(double)                                            |
+| RADIANS | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#toRadians(double)                                            |
+| ABS     | INT32 / INT64 / FLOAT / DOUBLE | 与输入序列的实际类型一致 |                                              | Math#abs(int) / Math#abs(long) /Math#abs(float) /Math#abs(double) |
+| SIGN    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#signum(double)                                               |
+| CEIL    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#ceil(double)                                                 |
+| FLOOR   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#floor(double)                                                |
+| ROUND   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   | `places`:四舍五入有效位数,正数为小数点后面的有效位数,负数为整数位的有效位数 | Math#rint(Math#pow(10,places))/Math#pow(10,places)                         |
+| EXP     | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#exp(double)                                                  |
+| LN      | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#log(double)                                                  |
+| LOG10   | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#log10(double)                                                |
+| SQRT    | INT32 / INT64 / FLOAT / DOUBLE | DOUBLE                   |                                              | Math#sqrt(double)                                                 |
 
 
 详细说明及示例见文档 [算数运算符和函数](./Mathematical.md)。
diff --git a/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinScalarFunctionEnum.java b/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinScalarFunctionEnum.java
index 9518a2d546..3784af7c61 100644
--- a/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinScalarFunctionEnum.java
+++ b/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinScalarFunctionEnum.java
@@ -23,6 +23,7 @@ public enum BuiltinScalarFunctionEnum {
   DIFF("diff"),
   CAST("cast"),
   REPLACE("replace"),
+  ROUND("round");
   ;
 
   private final String functionName;
diff --git a/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinTimeSeriesGeneratingFunctionEnum.java b/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinTimeSeriesGeneratingFunctionEnum.java
index 2b98a13fd9..cf3b130a48 100644
--- a/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinTimeSeriesGeneratingFunctionEnum.java
+++ b/integration-test/src/main/java/org/apache/iotdb/itbase/constant/BuiltinTimeSeriesGeneratingFunctionEnum.java
@@ -38,7 +38,6 @@ public enum BuiltinTimeSeriesGeneratingFunctionEnum {
   SIGN("SIGN"),
   CEIL("CEIL"),
   FLOOR("FLOOR"),
-  ROUND("ROUND"),
   EXP("EXP"),
   LN("LN"),
   LOG10("LOG10"),
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBRoundFunctionIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBRoundFunctionIT.java
new file mode 100644
index 0000000000..a34e069baa
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/builtinfunction/scalar/IoTDBRoundFunctionIT.java
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.it.builtinfunction.scalar;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import static org.apache.iotdb.db.it.utils.TestUtils.assertTestFail;
+import static org.apache.iotdb.db.it.utils.TestUtils.prepareData;
+import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest;
+import static org.apache.iotdb.itbase.constant.TestConstant.TIMESTAMP_STR;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBRoundFunctionIT {
+  protected static final String[] SQLs =
+      new String[] {
+        "CREATE DATABASE root.db",
+        "CREATE DATABASE root.db1",
+        "CREATE TIMESERIES root.db.d1.s1 WITH DATATYPE=INT32, ENCODING=PLAIN tags(city=Beijing)",
+        "CREATE TIMESERIES root.db.d1.s2 WITH DATATYPE=INT64, ENCODING=PLAIN tags(city=Nanjing)",
+        "CREATE TIMESERIES root.db.d1.s3 WITH DATATYPE=DOUBLE, ENCODING=PLAIN tags(city=Nanjing)",
+        "CREATE TIMESERIES root.db.d1.s4 WITH DATATYPE=FLOAT, ENCODING=PLAIN tags(city=Nanjing)",
+        "CREATE TIMESERIES root.db.d1.s5 WITH DATATYPE=BOOLEAN, ENCODING=PLAIN tags(city=Nanjing)",
+        "CREATE TIMESERIES root.db.d1.s6 WITH DATATYPE=TEXT, ENCODING=PLAIN tags(city=Nanjing)",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(1, 2, 3, 0.11234, 101.143445345,true,null)",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(2, 2, 4, 10.11234, 20.1443465345,true,'sss')",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(3, 2, 555, 120.161234, 20.61437245345,true,'sss')",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(4, 2, 12341234, 101.131234, null,true,'sss')",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(5, 2, 55678, 90.116234, 20.8143454345,true,'sss')",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(6, 2, 12355, null, 60.71443345345,true,'sss')",
+        "INSERT INTO root.db.d1(timestamp,s1,s2,s3,s4,s5,s6) values(1678695379764, 2, 12345, 120.511234, 10.143425345,null,'sss')",
+        "flush"
+      };
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    EnvFactory.getEnv().getConfig().getCommonConfig().setPartitionInterval(1000);
+    EnvFactory.getEnv().initClusterEnvironment();
+    prepareData(SQLs);
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  @Test
+  public void testRound() {
+    String[] intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s1)"};
+    String[] intRetArray =
+        new String[] {
+          "1,2.0,", "2,2.0,", "3,2.0,", "4,2.0,", "5,2.0,", "6,2.0,", "1678695379764,2.0,",
+        };
+    resultSetEqualTest("select round(s1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s2)"};
+    intRetArray =
+        new String[] {
+          "1,3.0,",
+          "2,4.0,",
+          "3,555.0,",
+          "4,1.2341234E7,",
+          "5,55678.0,",
+          "6,12355.0,",
+          "1678695379764,12345.0,",
+        };
+    resultSetEqualTest("select round(s2) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s3)"};
+    intRetArray =
+        new String[] {
+          "1,0.0,", "2,10.0,", "3,120.0,", "4,101.0,", "5,90.0,", "1678695379764,121.0,",
+        };
+    resultSetEqualTest("select round(s3) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s4)"};
+    intRetArray =
+        new String[] {
+          "1,101.0,", "2,20.0,", "3,21.0,", "5,21.0,", "6,61.0,", "1678695379764,10.0,",
+        };
+    resultSetEqualTest("select round(s4) from root.**", intExpectedHeader, intRetArray);
+  }
+
+  @Test
+  public void testRoundWithPlaces() {
+    String[] intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s1,1)"};
+    String[] intRetArray =
+        new String[] {
+          "1,2.0,", "2,2.0,", "3,2.0,", "4,2.0,", "5,2.0,", "6,2.0,", "1678695379764,2.0,",
+        };
+    resultSetEqualTest("select round(s1,1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s2,1)"};
+    intRetArray =
+        new String[] {
+          "1,3.0,",
+          "2,4.0,",
+          "3,555.0,",
+          "4,1.2341234E7,",
+          "5,55678.0,",
+          "6,12355.0,",
+          "1678695379764,12345.0,",
+        };
+    resultSetEqualTest("select round(s2,1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s3,1)"};
+    intRetArray =
+        new String[] {
+          "1,0.1,", "2,10.1,", "3,120.2,", "4,101.1,", "5,90.1,", "1678695379764,120.5,",
+        };
+    resultSetEqualTest("select round(s3,1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s3,2)"};
+    intRetArray =
+        new String[] {
+          "1,0.11,", "2,10.11,", "3,120.16,", "4,101.13,", "5,90.12,", "1678695379764,120.51,",
+        };
+    resultSetEqualTest("select round(s3,2) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s3,3)"};
+    intRetArray =
+        new String[] {
+          "1,0.112,",
+          "2,10.112,",
+          "3,120.161,",
+          "4,101.131,",
+          "5,90.116,",
+          "1678695379764,120.511,",
+        };
+    resultSetEqualTest("select round(s3,3) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s3,4)"};
+    intRetArray =
+        new String[] {
+          "1,0.1123,",
+          "2,10.1123,",
+          "3,120.1612,",
+          "4,101.1312,",
+          "5,90.1162,",
+          "1678695379764,120.5112,",
+        };
+    resultSetEqualTest("select round(s3,4) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s4,5)"};
+    intRetArray =
+        new String[] {
+          "1,101.14345,",
+          "2,20.14435,",
+          "3,20.61437,",
+          "5,20.81435,",
+          "6,60.71443,",
+          "1678695379764,10.14342,",
+        };
+    resultSetEqualTest("select round(s4,5) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s4,1)"};
+    intRetArray =
+        new String[] {
+          "1,101.1,", "2,20.1,", "3,20.6,", "5,20.8,", "6,60.7,", "1678695379764,10.1,",
+        };
+    resultSetEqualTest("select round(s4,1) from root.**", intExpectedHeader, intRetArray);
+  }
+
+  @Test
+  public void testRoundWithNegativePlaces() {
+    String[] intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s1,-1)"};
+    String[] intRetArray =
+        new String[] {
+          "1,0.0,", "2,0.0,", "3,0.0,", "4,0.0,", "5,0.0,", "6,0.0,", "1678695379764,0.0,",
+        };
+    resultSetEqualTest("select round(s1,-1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s2,-1)"};
+    intRetArray =
+        new String[] {
+          "1,0.0,",
+          "2,0.0,",
+          "3,560.0,",
+          "4,1.234123E7,",
+          "5,55680.0,",
+          "6,12360.0,",
+          "1678695379764,12340.0,",
+        };
+    resultSetEqualTest("select round(s2,-1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s3,-1)"};
+    intRetArray =
+        new String[] {
+          "1,0.0,", "2,10.0,", "3,120.0,", "4,100.0,", "5,90.0,", "1678695379764,120.0,",
+        };
+    resultSetEqualTest("select round(s3,-1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {TIMESTAMP_STR, "ROUND(root.db.d1.s4,-1)"};
+    intRetArray =
+        new String[] {
+          "1,100.0,", "2,20.0,", "3,20.0,", "5,20.0,", "6,60.0,", "1678695379764,10.0,",
+        };
+    resultSetEqualTest("select round(s4,-1) from root.**", intExpectedHeader, intRetArray);
+  }
+
+  @Test
+  public void testWithUDF() {
+    String[] intExpectedHeader =
+        new String[] {"Time,change_points(root.db.d1.s2),ROUND(root.db.d1.s2,1)"};
+    String[] intRetArray =
+        new String[] {
+          "1,3,3.0,",
+          "2,4,4.0,",
+          "3,555,555.0,",
+          "4,12341234,1.2341234E7,",
+          "5,55678,55678.0,",
+          "6,12355,12355.0,",
+          "1678695379764,12345,12345.0,",
+        };
+    resultSetEqualTest(
+        "select change_points(s2),ROUND(s2,1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {"Time,change_points(root.db.d1.s2),ROUND(root.db.d1.s3,1)"};
+    intRetArray =
+        new String[] {
+          "1,3,0.1,",
+          "2,4,10.1,",
+          "3,555,120.2,",
+          "4,12341234,101.1,",
+          "5,55678,90.1,",
+          "6,12355,null,",
+          "1678695379764,12345,120.5,",
+        };
+    resultSetEqualTest(
+        "select change_points(s2),ROUND(s3,1) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {"Time,change_points(root.db.d1.s2),ROUND(root.db.d1.s3,2)"};
+    intRetArray =
+        new String[] {
+          "1,3,0.11,",
+          "2,4,10.11,",
+          "3,555,120.16,",
+          "4,12341234,101.13,",
+          "5,55678,90.12,",
+          "6,12355,null,",
+          "1678695379764,12345,120.51,",
+        };
+    resultSetEqualTest(
+        "select change_points(s2),ROUND(s3,2) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {"Time,change_points(root.db.d1.s2),ROUND(root.db.d1.s3,3)"};
+    intRetArray =
+        new String[] {
+          "1,3,0.112,",
+          "2,4,10.112,",
+          "3,555,120.161,",
+          "4,12341234,101.131,",
+          "5,55678,90.116,",
+          "6,12355,null,",
+          "1678695379764,12345,120.511,",
+        };
+    resultSetEqualTest(
+        "select change_points(s2),ROUND(s3,3) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {"Time,change_points(root.db.d1.s2),ROUND(root.db.d1.s3,4)"};
+    intRetArray =
+        new String[] {
+          "1,3,0.1123,",
+          "2,4,10.1123,",
+          "3,555,120.1612,",
+          "4,12341234,101.1312,",
+          "5,55678,90.1162,",
+          "6,12355,null,",
+          "1678695379764,12345,120.5112,",
+        };
+    resultSetEqualTest(
+        "select change_points(s2),ROUND(s3,4) from root.**", intExpectedHeader, intRetArray);
+
+    intExpectedHeader = new String[] {"Time,change_points(root.db.d1.s2),ROUND(root.db.d1.s4,5)"};
+    intRetArray =
+        new String[] {
+          "1,3,101.14345,",
+          "2,4,20.14435,",
+          "3,555,20.61437,",
+          "4,12341234,null,",
+          "5,55678,20.81435,",
+          "6,12355,60.71443,",
+          "1678695379764,12345,10.14342,",
+        };
+    resultSetEqualTest(
+        "select change_points(s2),ROUND(s4,5) from root.**", intExpectedHeader, intRetArray);
+  }
+
+  @Test
+  public void testRoundBooleanAndText() {
+    assertTestFail(
+        "select round(s5) from root.**",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode()
+            + ": Input series of Scalar function [ROUND] only supports numeric data types [INT32, INT64, FLOAT, DOUBLE]");
+
+    assertTestFail(
+        "select round(s6) from root.**",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode()
+            + ": Input series of Scalar function [ROUND] only supports numeric data types [INT32, INT64, FLOAT, DOUBLE]");
+  }
+}
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinScalarFunction.java b/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinScalarFunction.java
index 691f225eb5..d42ad6e39b 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinScalarFunction.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinScalarFunction.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 public enum BuiltinScalarFunction {
   DIFF("diff"),
   CAST("cast"),
+  ROUND("round"),
   REPLACE("replace"),
   ;
 
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java b/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java
index c5e8c2767f..d790d9aeba 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java
@@ -50,7 +50,6 @@ public enum BuiltinTimeSeriesGeneratingFunction {
   SIGN("SIGN", UDTFSign.class),
   CEIL("CEIL", UDTFCeil.class),
   FLOOR("FLOOR", UDTFFloor.class),
-  ROUND("ROUND", UDTFRound.class),
   EXP("EXP", UDTFExp.class),
   LN("LN", UDTFLog.class),
   LOG10("LOG10", UDTFLog10.class),
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFRound.java b/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFRound.java
deleted file mode 100644
index 85adb5f437..0000000000
--- a/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFRound.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.iotdb.commons.udf.builtin;
-
-public class UDTFRound extends UDTFMath {
-
-  @Override
-  protected void setTransformer() {
-    transformer = Math::rint;
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/constant/SqlConstant.java b/server/src/main/java/org/apache/iotdb/db/constant/SqlConstant.java
index 020073bb12..74fbbef9ab 100644
--- a/server/src/main/java/org/apache/iotdb/db/constant/SqlConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/constant/SqlConstant.java
@@ -63,6 +63,8 @@ public class SqlConstant {
 
   public static final String CAST_FUNCTION = "CAST";
   public static final String CAST_TYPE = "type";
+  public static final String ROUND_FUNCTION = "ROUND";
+  public static final String ROUND_PLACES = "PLACES";
   public static final String REPLACE_FUNCTION = "REPLACE";
   public static final String REPLACE_FROM = "FROM";
   public static final String REPLACE_TO = "TO";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java
index 720a17e80e..6a36dc93c9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java
@@ -263,7 +263,7 @@ public class FunctionExpression extends Expression {
         }
       }
       if (!functionAttributes.isEmpty()) {
-        // Some builtin-scalar function may have different header.
+        // Some built-in scalar functions may have different header.
         if (BuiltinScalarFunction.contains(functionName)) {
           BuiltInScalarFunctionHelperFactory.createHelper(functionName)
               .appendFunctionAttributes(!expressions.isEmpty(), builder, functionAttributes);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelper.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelper.java
index 7525a4f155..ee71e1874f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelper.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelper.java
@@ -80,8 +80,8 @@ public interface BuiltInScalarFunctionHelper extends BuiltInFunctionHelper {
       FunctionExpression expression, LayerPointReader layerPointReader);
 
   /**
-   * Some builtin-scalar function may have a different header. This method will be called by {@link
-   * FunctionExpression#getExpressionStringInternal()} )}
+   * Some built-in scalar functions may have a different header. This method will be called by
+   * {@link FunctionExpression#getExpressionStringInternal()} )}
    *
    * @param builder String builder in FunctionExpression. Append function attributes through it.
    * @param functionAttributes attributes of the function
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelperFactory.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelperFactory.java
index f7d09a81df..f47128b81e 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelperFactory.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/BuiltInScalarFunctionHelperFactory.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.db.mpp.plan.expression.multi.builtin;
 import org.apache.iotdb.db.mpp.plan.expression.multi.builtin.helper.CastFunctionHelper;
 import org.apache.iotdb.db.mpp.plan.expression.multi.builtin.helper.DiffFunctionHelper;
 import org.apache.iotdb.db.mpp.plan.expression.multi.builtin.helper.ReplaceFunctionHelper;
+import org.apache.iotdb.db.mpp.plan.expression.multi.builtin.helper.RoundFunctionHelper;
 
 public class BuiltInScalarFunctionHelperFactory {
   public static BuiltInScalarFunctionHelper createHelper(String functionName) {
@@ -33,6 +34,8 @@ public class BuiltInScalarFunctionHelperFactory {
         return new CastFunctionHelper();
       case "REPLACE":
         return new ReplaceFunctionHelper();
+      case "ROUND":
+        return new RoundFunctionHelper();
       default:
         throw new IllegalArgumentException(
             String.format("Invalid scalar function [%s].", functionName));
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/helper/RoundFunctionHelper.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/helper/RoundFunctionHelper.java
new file mode 100644
index 0000000000..d26b3decb0
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/builtin/helper/RoundFunctionHelper.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.plan.expression.multi.builtin.helper;
+
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
+import org.apache.iotdb.db.mpp.plan.expression.multi.builtin.BuiltInScalarFunctionHelper;
+import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
+import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.scalar.RoundFunctionColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
+import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.scalar.RoundFunctionTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
+
+import java.util.Map;
+
+import static org.apache.iotdb.db.constant.SqlConstant.ROUND_PLACES;
+import static org.apache.iotdb.db.mpp.plan.parser.ASTVisitor.checkFunctionExpressionInputSize;
+
+public class RoundFunctionHelper implements BuiltInScalarFunctionHelper {
+  @Override
+  public void checkBuiltInScalarFunctionInputSize(FunctionExpression functionExpression)
+      throws SemanticException {
+    checkFunctionExpressionInputSize(
+        functionExpression.getExpressionString(), functionExpression.getExpressions().size(), 1);
+  }
+
+  @Override
+  public void checkBuiltInScalarFunctionInputDataType(TSDataType tsDataType)
+      throws SemanticException {
+    if (tsDataType.isNumeric()) {
+      return;
+    }
+    throw new SemanticException(
+        "Input series of Scalar function [ROUND] only supports numeric data types [INT32, INT64, FLOAT, DOUBLE]");
+  }
+
+  @Override
+  public TSDataType getBuiltInScalarFunctionReturnType(FunctionExpression functionExpression) {
+    return TSDataType.DOUBLE;
+  }
+
+  @Override
+  public ColumnTransformer getBuiltInScalarFunctionColumnTransformer(
+      FunctionExpression expression, ColumnTransformer columnTransformer) {
+    return new RoundFunctionColumnTransformer(
+        TypeFactory.getType(this.getBuiltInScalarFunctionReturnType(expression)),
+        columnTransformer,
+        Integer.parseInt(expression.getFunctionAttributes().getOrDefault(ROUND_PLACES, "0")));
+  }
+
+  @Override
+  public Transformer getBuiltInScalarFunctionTransformer(
+      FunctionExpression expression, LayerPointReader layerPointReader) {
+    return new RoundFunctionTransformer(
+        layerPointReader,
+        this.getBuiltInScalarFunctionReturnType(expression),
+        Integer.parseInt(expression.getFunctionAttributes().getOrDefault(ROUND_PLACES, "0")));
+  }
+
+  @Override
+  public void appendFunctionAttributes(
+      boolean hasExpression, StringBuilder builder, Map<String, String> functionAttributes) {
+    builder.append(",").append(functionAttributes.get(ROUND_PLACES));
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index 580ed76379..c47fed94a9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -212,6 +212,8 @@ import static org.apache.iotdb.db.constant.SqlConstant.CAST_TYPE;
 import static org.apache.iotdb.db.constant.SqlConstant.REPLACE_FROM;
 import static org.apache.iotdb.db.constant.SqlConstant.REPLACE_FUNCTION;
 import static org.apache.iotdb.db.constant.SqlConstant.REPLACE_TO;
+import static org.apache.iotdb.db.constant.SqlConstant.ROUND_FUNCTION;
+import static org.apache.iotdb.db.constant.SqlConstant.ROUND_PLACES;
 import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_RESULT_NODES;
 
 /** Parse AST to Statement. */
@@ -2366,6 +2368,8 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
       return parseCastFunction(context, canUseFullPath);
     } else if (context.REPLACE() != null) {
       return parseReplaceFunction(context, canUseFullPath);
+    } else if (context.ROUND() != null) {
+      return parseRoundFunction(context, canUseFullPath);
     }
     throw new UnsupportedOperationException();
   }
@@ -2387,6 +2391,16 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
     return functionExpression;
   }
 
+  private Expression parseRoundFunction(
+      IoTDBSqlParser.ScalarFunctionExpressionContext roundClause, boolean canUseFullPath) {
+    FunctionExpression functionExpression = new FunctionExpression(ROUND_FUNCTION);
+    functionExpression.addExpression(parseExpression(roundClause.input, canUseFullPath));
+    if (roundClause.places != null) {
+      functionExpression.addAttribute(ROUND_PLACES, parseConstant(roundClause.constant()));
+    }
+    return functionExpression;
+  }
+
   private Expression parseFunctionExpression(
       IoTDBSqlParser.ExpressionContext functionClause, boolean canUseFullPath) {
     FunctionExpression functionExpression =
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/transformation/dag/column/unary/scalar/RoundFunctionColumnTransformer.java b/server/src/main/java/org/apache/iotdb/db/mpp/transformation/dag/column/unary/scalar/RoundFunctionColumnTransformer.java
new file mode 100644
index 0000000000..193db12890
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/transformation/dag/column/unary/scalar/RoundFunctionColumnTransformer.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.transformation.dag.column.unary.scalar;
+
+import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.UnaryColumnTransformer;
+import org.apache.iotdb.tsfile.read.common.block.column.Column;
+import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
+import org.apache.iotdb.tsfile.read.common.type.Type;
+import org.apache.iotdb.tsfile.read.common.type.TypeEnum;
+
+public class RoundFunctionColumnTransformer extends UnaryColumnTransformer {
+
+  protected int places;
+
+  public RoundFunctionColumnTransformer(
+      Type returnType, ColumnTransformer childColumnTransformer, int places) {
+    super(returnType, childColumnTransformer);
+    this.places = places;
+  }
+
+  @Override
+  protected void doTransform(Column column, ColumnBuilder columnBuilder) {
+    TypeEnum sourceType = childColumnTransformer.getType().getTypeEnum();
+    for (int i = 0, n = column.getPositionCount(); i < n; i++) {
+      if (!column.isNull(i)) {
+        switch (sourceType) {
+          case INT32:
+            columnBuilder.writeDouble(
+                Math.rint(column.getInt(i) * Math.pow(10, places)) / Math.pow(10, places));
+            break;
+          case INT64:
+            columnBuilder.writeDouble(
+                Math.rint(column.getLong(i) * Math.pow(10, places)) / Math.pow(10, places));
+            break;
+          case FLOAT:
+            columnBuilder.writeDouble(
+                Math.rint(column.getFloat(i) * Math.pow(10, places)) / Math.pow(10, places));
+            break;
+          case DOUBLE:
+            columnBuilder.writeDouble(
+                Math.rint(column.getDouble(i) * Math.pow(10, places)) / Math.pow(10, places));
+            break;
+          default:
+            throw new UnsupportedOperationException(
+                String.format(
+                    "Unsupported source dataType: %s",
+                    childColumnTransformer.getType().getTypeEnum()));
+        }
+      } else {
+        columnBuilder.appendNull();
+      }
+    }
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/transformation/dag/transformer/unary/scalar/RoundFunctionTransformer.java b/server/src/main/java/org/apache/iotdb/db/mpp/transformation/dag/transformer/unary/scalar/RoundFunctionTransformer.java
new file mode 100644
index 0000000000..2dff19193e
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/transformation/dag/transformer/unary/scalar/RoundFunctionTransformer.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.scalar;
+
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
+import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.UnaryTransformer;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import java.io.IOException;
+
+public class RoundFunctionTransformer extends UnaryTransformer {
+  private final TSDataType targetDataType;
+
+  protected int places;
+
+  public RoundFunctionTransformer(
+      LayerPointReader layerPointReader, TSDataType targetDataType, int places) {
+    super(layerPointReader);
+    this.targetDataType = targetDataType;
+    this.places = places;
+  }
+
+  @Override
+  public TSDataType getDataType() {
+    return targetDataType;
+  }
+
+  @Override
+  protected void transformAndCache() throws QueryProcessException, IOException {
+    switch (layerPointReaderDataType) {
+      case INT32:
+        cachedDouble =
+            Math.rint(layerPointReader.currentInt() * Math.pow(10, places)) / Math.pow(10, places);
+        return;
+      case INT64:
+        cachedDouble =
+            Math.rint(layerPointReader.currentLong() * Math.pow(10, places)) / Math.pow(10, places);
+        return;
+      case FLOAT:
+        cachedDouble =
+            Math.rint(layerPointReader.currentFloat() * Math.pow(10, places))
+                / Math.pow(10, places);
+        return;
+      case DOUBLE:
+        cachedDouble =
+            Math.rint(layerPointReader.currentDouble() * Math.pow(10, places))
+                / Math.pow(10, places);
+        return;
+      default:
+        throw new UnsupportedOperationException(
+            String.format("Unsupported source dataType: %s", layerPointReaderDataType));
+    }
+  }
+}