You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by zy...@apache.org on 2023/05/09 01:01:42 UTC

[iotdb] branch master updated: Support Create and Query Schema of Logical View (#9742)

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

zyk 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 f579e3ca0d Support Create and Query Schema of Logical View (#9742)
f579e3ca0d is described below

commit f579e3ca0d66d837f794cf2b9bbd850ddad5019e
Author: 橘子 <70...@users.noreply.github.com>
AuthorDate: Tue May 9 09:01:37 2023 +0800

    Support Create and Query Schema of Logical View (#9742)
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  22 ++
 .../antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4  |   4 +
 client-py/tests/test_dataframe.py                  |   2 +
 .../apache/iotdb/db/it/query/IoTDBResultSetIT.java |   2 +
 .../iotdb/db/it/schema/IoTDBExtendTemplateIT.java  |  32 +-
 .../iotdb/db/it/schema/IoTDBMetadataFetchIT.java   |  44 +--
 .../iotdb/zeppelin/it/IoTDBInterpreterIT.java      |  14 +-
 .../node/common/AbstractMeasurementMNode.java      |   4 +
 .../schema/node/role/IMeasurementMNode.java        |   2 +
 .../commons/schema/node/utils/IMNodeFactory.java   |   4 +
 .../schemaregion/rocksdb/RSchemaRegion.java        |   7 +
 .../rocksdb/mnode/RMeasurementMNode.java           |   5 +
 .../metadata/tagSchemaRegion/TagSchemaRegion.java  |   7 +
 .../apache/iotdb/db/metadata/MetadataConstant.java |   6 +
 .../mnode/config/factory/ConfigMNodeFactory.java   |   7 +
 .../mnode/mem/factory/MemMNodeFactory.java         |  14 +
 ...MeasurementMNode.java => LogicalViewMNode.java} |  30 +-
 .../metadata/mnode/mem/impl/LogicalViewSchema.java | 215 +++++++++++
 .../metadata/mnode/mem/impl/MeasurementMNode.java  |   5 +
 .../metadata/mnode/mem/info/LogicalViewInfo.java   | 161 +++++++++
 .../schemafile/factory/CacheMNodeFactory.java      |   7 +
 .../schemafile/impl/CachedMeasurementMNode.java    |   5 +
 .../db/metadata/mtree/MTreeBelowSGCachedImpl.java  |  10 +-
 .../db/metadata/mtree/MTreeBelowSGMemoryImpl.java  |  75 +++-
 .../mtree/snapshot/MemMTreeSnapshotUtil.java       |  41 ++-
 .../plan/schemaregion/SchemaRegionPlanType.java    |   2 +
 .../plan/schemaregion/SchemaRegionPlanVisitor.java |   5 +
 .../impl/SchemaRegionPlanDeserializer.java         |  24 ++
 .../impl/SchemaRegionPlanSerializer.java           |  27 ++
 .../impl/SchemaRegionPlanTxtSerializer.java        |  21 ++
 .../impl/write/CreateLogicalViewPlanImpl.java      |  75 ++++
 .../schemaregion/result/ShowTimeSeriesResult.java  |  14 +-
 .../schemaregion/write/ICreateLogicalViewPlan.java |  66 ++++
 .../metadata/query/info/ITimeSeriesSchemaInfo.java |   6 +-
 .../db/metadata/schemaregion/ISchemaRegion.java    |   5 +
 .../schemaregion/SchemaRegionMemoryImpl.java       |  40 +++
 .../schemaregion/SchemaRegionSchemaFileImpl.java   |   7 +
 .../view/viewExpression/ViewExpression.java        | 318 +++++++++++++++++
 .../view/viewExpression/ViewExpressionType.java    |  76 ++++
 .../binary/BinaryViewExpression.java               | 119 +++++++
 .../binary/arithmetic/AdditionViewExpression.java  |  61 ++++
 .../arithmetic/ArithmeticBinaryViewExpression.java |  52 +++
 .../binary/arithmetic/DivisionViewExpression.java  |  61 ++++
 .../binary/arithmetic/ModuloViewExpression.java    |  61 ++++
 .../arithmetic/MultiplicationViewExpression.java   |  63 ++++
 .../arithmetic/SubtractionViewExpression.java      |  61 ++++
 .../compare/CompareBinaryViewExpression.java       |  52 +++
 .../binary/compare/EqualToViewExpression.java      |  57 +++
 .../binary/compare/GreaterEqualViewExpression.java |  57 +++
 .../binary/compare/GreaterThanViewExpression.java  |  57 +++
 .../binary/compare/LessEqualViewExpression.java    |  57 +++
 .../binary/compare/LessThanViewExpression.java     |  57 +++
 .../binary/compare/NonEqualViewExpression.java     |  57 +++
 .../binary/logic/LogicAndViewExpression.java       |  57 +++
 .../binary/logic/LogicBinaryViewExpression.java    |  52 +++
 .../binary/logic/LogicOrViewExpression.java        |  57 +++
 .../viewExpression/leaf/ConstantViewOperand.java   |  98 ++++++
 .../viewExpression/leaf/LeafViewOperand.java}      |  28 +-
 .../view/viewExpression/leaf/NullViewOperand.java  |  61 ++++
 .../viewExpression/leaf/TimeSeriesViewOperand.java |  87 +++++
 .../viewExpression/leaf/TimestampViewOperand.java  |  72 ++++
 .../multi/FunctionViewExpression.java              | 198 +++++++++++
 .../ternary/BetweenViewExpression.java             | 111 ++++++
 .../ternary/TernaryViewExpression.java             | 105 ++++++
 .../viewExpression/unary/InViewExpression.java     | 106 ++++++
 .../viewExpression/unary/IsNullViewExpression.java |  89 +++++
 .../viewExpression/unary/LikeViewExpression.java   | 163 +++++++++
 .../unary/LogicNotViewExpression.java              |  61 ++++
 .../unary/NegationViewExpression.java              |  61 ++++
 .../unary/RegularViewExpression.java               | 105 ++++++
 .../viewExpression/unary/UnaryViewExpression.java  |  73 ++++
 .../visitor/GetSourcePathsVisitor.java             |  95 +++++
 .../visitor/TransformToExpressionVisitor.java      | 320 +++++++++++++++++
 .../visitor/ViewExpressionVisitor.java             | 219 ++++++++++++
 .../metadata/visitor/SchemaExecutionVisitor.java   |  22 ++
 .../db/mpp/common/header/ColumnHeaderConstant.java |   6 +-
 .../execution/executor/RegionWriteExecutor.java    |  49 +++
 .../schema/source/TimeSeriesSchemaSource.java      |  14 +-
 .../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java  |  45 +++
 .../visitor/TransformToViewExpressionVisitor.java  | 391 +++++++++++++++++++++
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |  86 +++++
 .../db/mpp/plan/planner/LogicalPlanVisitor.java    |  21 ++
 .../mpp/plan/planner/plan/node/PlanNodeType.java   |   6 +-
 .../db/mpp/plan/planner/plan/node/PlanVisitor.java |   5 +
 .../node/metedata/write/CreateLogicalViewNode.java | 250 +++++++++++++
 .../iotdb/db/mpp/plan/statement/StatementType.java |   2 +
 .../db/mpp/plan/statement/StatementVisitor.java    |   7 +
 .../metadata/CreateLogicalViewStatement.java       | 246 +++++++++++++
 .../metadata/view/ViewExpressionToStringTest.java  | 183 ++++++++++
 89 files changed, 5745 insertions(+), 89 deletions(-)

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 d88e4533c6..4a95f1a812 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
@@ -63,6 +63,8 @@ ddlStatement
     | createModel | dropModel | showModels | showTrails
     // Quota
     | setSpaceQuota | showSpaceQuota | setThrottleQuota | showThrottleQuota
+    // View
+    | createLogicalView
     ;
 
 dmlStatement
@@ -530,6 +532,26 @@ showTrails
     : SHOW TRAILS modelId=identifier
     ;
 
+// Create Logical View
+createLogicalView
+    : CREATE VIEW viewTargetPaths AS viewSourcePaths
+    ;
+
+viewSuffixPaths
+    : nodeNameWithoutWildcard (DOT nodeNameWithoutWildcard)*
+    ;
+
+viewTargetPaths
+    : fullPath (COMMA fullPath)*
+    | prefixPath LR_BRACKET viewSuffixPaths (COMMA viewSuffixPaths)* RR_BRACKET
+    ;
+
+viewSourcePaths
+    : fullPath (COMMA fullPath)*
+    | prefixPath LR_BRACKET viewSuffixPaths (COMMA viewSuffixPaths)* RR_BRACKET
+    | selectClause fromClause
+    ;
+
 /**
  * 3. Data Manipulation Language (DML)
  */
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 fb7c5af931..b702f0ec25 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
@@ -810,6 +810,10 @@ VERSION
     : V E R S I O N
     ;
 
+VIEW
+    : V I E W
+    ;
+
 WATERMARK_EMBEDDING
     : W A T E R M A R K '_' E M B E D D I N G
     ;
diff --git a/client-py/tests/test_dataframe.py b/client-py/tests/test_dataframe.py
index 801b7c1bcd..7cdabac6e0 100644
--- a/client-py/tests/test_dataframe.py
+++ b/client-py/tests/test_dataframe.py
@@ -71,6 +71,7 @@ def test_non_time_query():
         "Attributes",
         "Deadband",
         "DeadbandParameters",
+        "ViewType",
     ]
     assert_array_equal(
         df.values,
@@ -86,6 +87,7 @@ def test_non_time_query():
                 None,
                 None,
                 None,
+                "",
             ]
         ],
     )
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
index 57e246c09f..d9d006f2fa 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
@@ -177,6 +177,8 @@ public class IoTDBResultSetIT {
             + ColumnHeaderConstant.DEADBAND
             + ","
             + ColumnHeaderConstant.DEADBAND_PARAMETERS
+            + ","
+            + ColumnHeaderConstant.VIEW_TYPE
             + ",";
     resultSetEqualTest("show timeseries root.sg1.**", expectedHeader, emptyResultSet);
   }
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBExtendTemplateIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBExtendTemplateIT.java
index 1816c17adc..a1fddcca81 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBExtendTemplateIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBExtendTemplateIT.java
@@ -87,10 +87,10 @@ public class IoTDBExtendTemplateIT extends AbstractSchemaIT {
           new Set[] {
             new HashSet<>(
                 Arrays.asList(
-                    "root.db.d1.s1,null,root.db,INT64,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s2,null,root.db,DOUBLE,RLE,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s3,null,root.db,INT64,RLE,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s4,null,root.db,DOUBLE,GORILLA,SNAPPY,null,null,null,null,"))
+                    "root.db.d1.s1,null,root.db,INT64,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s2,null,root.db,DOUBLE,RLE,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s3,null,root.db,INT64,RLE,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s4,null,root.db,DOUBLE,GORILLA,SNAPPY,null,null,null,null,,"))
           };
       for (int n = 0; n < sqls.length; n++) {
         String sql = sqls[n];
@@ -140,18 +140,18 @@ public class IoTDBExtendTemplateIT extends AbstractSchemaIT {
           new Set[] {
             new HashSet<>(
                 Arrays.asList(
-                    "root.db.d1.s1,null,root.db,INT64,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s2,null,root.db,DOUBLE,RLE,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s3,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s4,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db.d1.s5,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db.d2.s1,null,root.db,INT64,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.db.d2.s2,null,root.db,DOUBLE,RLE,SNAPPY,null,null,null,null,",
-                    "root.db.d2.s3,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db.d2.s4,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db.d2.s5,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db1.d1.s2,null,root.db1,FLOAT,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.db1.d1.s3,null,root.db1,FLOAT,GORILLA,SNAPPY,null,null,null,null,"))
+                    "root.db.d1.s1,null,root.db,INT64,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s2,null,root.db,DOUBLE,RLE,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s3,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s4,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db.d1.s5,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db.d2.s1,null,root.db,INT64,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.db.d2.s2,null,root.db,DOUBLE,RLE,SNAPPY,null,null,null,null,,",
+                    "root.db.d2.s3,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db.d2.s4,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db.d2.s5,null,root.db,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db1.d1.s2,null,root.db1,FLOAT,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.db1.d1.s3,null,root.db1,FLOAT,GORILLA,SNAPPY,null,null,null,null,,"))
           };
       for (int n = 0; n < sqls.length; n++) {
         String sql = sqls[n];
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
index 9c877983a2..7c1774d82d 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
@@ -114,27 +114,27 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT {
           new Set[] {
             new HashSet<>(
                 Collections.singletonList(
-                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,")),
+                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,")),
             new HashSet<>(
                 Arrays.asList(
-                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt02.s1,null,root.ln.wf01.wt02,INT32,RLE,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt02.s2,null,root.ln.wf01.wt02,DOUBLE,GORILLA,SNAPPY,null,null,null,null,")),
+                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt02.s1,null,root.ln.wf01.wt02,INT32,RLE,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt02.s2,null,root.ln.wf01.wt02,DOUBLE,GORILLA,SNAPPY,null,null,null,null,,")),
             new HashSet<>(
                 Arrays.asList(
-                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,")),
+                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,,")),
             new HashSet<>(
                 Arrays.asList(
-                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt02.s1,null,root.ln.wf01.wt02,INT32,RLE,SNAPPY,null,null,null,null,",
-                    "root.ln.wf01.wt02.s2,null,root.ln.wf01.wt02,DOUBLE,GORILLA,SNAPPY,null,null,null,null,",
-                    "root.ln1.wf01.wt01.status,null,root.ln1.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.ln1.wf01.wt01.temperature,null,root.ln1.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,",
-                    "root.ln2.wf01.wt01.status,null,root.ln2.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,",
-                    "root.ln2.wf01.wt01.temperature,null,root.ln2.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,")),
+                    "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt02.s1,null,root.ln.wf01.wt02,INT32,RLE,SNAPPY,null,null,null,null,,",
+                    "root.ln.wf01.wt02.s2,null,root.ln.wf01.wt02,DOUBLE,GORILLA,SNAPPY,null,null,null,null,,",
+                    "root.ln1.wf01.wt01.status,null,root.ln1.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.ln1.wf01.wt01.temperature,null,root.ln1.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,,",
+                    "root.ln2.wf01.wt01.status,null,root.ln2.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,",
+                    "root.ln2.wf01.wt01.temperature,null,root.ln2.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,,")),
             new HashSet<>()
           };
       for (int n = 0; n < sqls.length; n++) {
@@ -623,8 +623,8 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT {
           "create aligned timeseries root.sg.d(s1(alias1) int32 tags('tag1'='v1', 'tag2'='v2'), s2 double attributes('attr3'='v3'))");
       String[] expected =
           new String[] {
-            "root.sg.d.s1,alias1,root.sg,INT32,RLE,SNAPPY,{\"tag1\":\"v1\",\"tag2\":\"v2\"},null,null,null,",
-            "root.sg.d.s2,null,root.sg,DOUBLE,GORILLA,SNAPPY,null,{\"attr3\":\"v3\"},null,null,"
+            "root.sg.d.s1,alias1,root.sg,INT32,RLE,SNAPPY,{\"tag1\":\"v1\",\"tag2\":\"v2\"},null,null,null,,",
+            "root.sg.d.s2,null,root.sg,DOUBLE,GORILLA,SNAPPY,null,{\"attr3\":\"v3\"},null,null,,"
           };
 
       int num = 0;
@@ -653,8 +653,8 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT {
       Set<String> standard =
           new HashSet<>(
               Arrays.asList(
-                  "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,",
-                  "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,"));
+                  "root.ln.wf01.wt01.temperature,null,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,null,null,null,null,,",
+                  "root.ln.wf01.wt01.status,null,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,null,null,null,null,,"));
       try (ResultSet resultSet = statement.executeQuery(sql)) {
         ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
         while (resultSet.next()) {
@@ -691,9 +691,9 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT {
       Set<String> standard =
           new HashSet<>(
               Arrays.asList(
-                  "root.sg1.d0.s0,null,root.sg1,INT32,RLE,SNAPPY,null,null,null,null,\n",
-                  "root.sg1.d0.s1,null,root.sg1,INT32,PLAIN,SNAPPY,null,null,SDT,{compdev=2},\n",
-                  "root.sg1.d0.s2,null,root.sg1,INT32,PLAIN,SNAPPY,null,null,SDT,{compdev=0.01, compmintime=2, compmaxtime=15},\n"));
+                  "root.sg1.d0.s0,null,root.sg1,INT32,RLE,SNAPPY,null,null,null,null,,\n",
+                  "root.sg1.d0.s1,null,root.sg1,INT32,PLAIN,SNAPPY,null,null,SDT,{compdev=2},,\n",
+                  "root.sg1.d0.s2,null,root.sg1,INT32,PLAIN,SNAPPY,null,null,SDT,{compdev=0.01, compmintime=2, compmaxtime=15},,\n"));
       try (ResultSet resultSet = statement.executeQuery("SHOW TIMESERIES root.sg1.d0.*")) {
         ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
         while (resultSet.next()) {
diff --git a/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java b/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
index ba6170c0cb..514b66c13e 100644
--- a/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
@@ -307,13 +307,13 @@ public class IoTDBInterpreterIT {
   public void testShowTimeseries() {
     InterpreterResult actual = interpreter.internalInterpret("show timeseries", null);
     String gt =
-        "Timeseries\tAlias\tDatabase\tDataType\tEncoding\tCompression\tTags\tAttributes\tDeadband\tDeadbandParameters\n"
-            + "root.test.wf01.wt01.temperature\tnull\troot.test.wf01\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\n"
-            + "root.test.wf01.wt01.status\tnull\troot.test.wf01\tBOOLEAN\tRLE\tSNAPPY\tnull\tnull\tnull\tnull\n"
-            + "root.test.wf01.wt01.hardware\tnull\troot.test.wf01\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\n"
-            + "root.test.wf02.wt02.temperature\tnull\troot.test.wf02\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\n"
-            + "root.test.wf02.wt02.status\tnull\troot.test.wf02\tBOOLEAN\tRLE\tSNAPPY\tnull\tnull\tnull\tnull\n"
-            + "root.test.wf02.wt02.hardware\tnull\troot.test.wf02\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull";
+        "Timeseries\tAlias\tDatabase\tDataType\tEncoding\tCompression\tTags\tAttributes\tDeadband\tDeadbandParameters\tViewType\n"
+            + "root.test.wf01.wt01.temperature\tnull\troot.test.wf01\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\t\n"
+            + "root.test.wf01.wt01.status\tnull\troot.test.wf01\tBOOLEAN\tRLE\tSNAPPY\tnull\tnull\tnull\tnull\t\n"
+            + "root.test.wf01.wt01.hardware\tnull\troot.test.wf01\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\t\n"
+            + "root.test.wf02.wt02.temperature\tnull\troot.test.wf02\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\t\n"
+            + "root.test.wf02.wt02.status\tnull\troot.test.wf02\tBOOLEAN\tRLE\tSNAPPY\tnull\tnull\tnull\tnull\t\n"
+            + "root.test.wf02.wt02.hardware\tnull\troot.test.wf02\tFLOAT\tGORILLA\tSNAPPY\tnull\tnull\tnull\tnull\t";
     Assert.assertNotNull(actual);
     Assert.assertEquals(Code.SUCCESS, actual.code());
     Assert.assertEquals(gt, actual.message().get(0).getData());
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/common/AbstractMeasurementMNode.java b/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/common/AbstractMeasurementMNode.java
index 602c5d8d3c..c8338deead 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/common/AbstractMeasurementMNode.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/common/AbstractMeasurementMNode.java
@@ -253,4 +253,8 @@ public abstract class AbstractMeasurementMNode<N extends IMNode<N>, BasicNode ex
   public int estimateSize() {
     return 8 + 8 + measurementInfo.estimateSize() + basicMNode.estimateSize();
   }
+
+  protected IMeasurementInfo getMeasurementInfo() {
+    return this.measurementInfo;
+  }
 }
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/role/IMeasurementMNode.java b/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/role/IMeasurementMNode.java
index 57ad4dd948..cbee170460 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/role/IMeasurementMNode.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/role/IMeasurementMNode.java
@@ -45,4 +45,6 @@ public interface IMeasurementMNode<N extends IMNode<N>> extends IMNode<N> {
   void setPreDeleted(boolean preDeleted);
 
   MeasurementPath getMeasurementPath();
+
+  public abstract boolean isLogicalView();
 }
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java b/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
index f8aaa669bc..da7a3c1dc5 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.commons.schema.node.utils;
 
 import org.apache.iotdb.commons.schema.node.IMNode;
+import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
 import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
 import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
 import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -39,4 +40,7 @@ public interface IMNodeFactory<N extends IMNode<N>> {
   N createAboveDatabaseMNode(N parent, String name);
 
   N createInternalMNode(N parent, String name);
+
+  IMeasurementMNode<N> createLogicalViewMNode(
+      IDeviceMNode<N> parent, String name, IMeasurementInfo measurementInfo);
 }
diff --git a/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/RSchemaRegion.java b/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/RSchemaRegion.java
index 4d5d9a9372..23deb238dd 100644
--- a/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/RSchemaRegion.java
+++ b/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/RSchemaRegion.java
@@ -50,6 +50,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.read.IShowTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.result.ShowTimeSeriesResult;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IActivateTemplateInClusterPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeactivateTemplatePlan;
@@ -702,6 +703,12 @@ public class RSchemaRegion implements ISchemaRegion {
     throw new UnsupportedOperationException();
   }
 
+  @Override
+  public void createLogicalView(ICreateLogicalViewPlan createLogicalViewPlan)
+      throws MetadataException {
+    throw new UnsupportedOperationException("createLogicalView is unsupported.");
+  }
+
   private void traverseOutcomeBasins(
       String[] nodes,
       int maxLevel,
diff --git a/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMeasurementMNode.java b/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMeasurementMNode.java
index 58a9708d44..faa398a8dd 100644
--- a/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMeasurementMNode.java
+++ b/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMeasurementMNode.java
@@ -100,6 +100,11 @@ public class RMeasurementMNode extends RMNode implements IMeasurementMNode<IMemM
     return result;
   }
 
+  @Override
+  public boolean isLogicalView() {
+    return false;
+  }
+
   @Override
   public IMeasurementSchema getSchema() {
     return schema;
diff --git a/schema-engine-tag/src/main/java/org/apache/iotdb/db/metadata/tagSchemaRegion/TagSchemaRegion.java b/schema-engine-tag/src/main/java/org/apache/iotdb/db/metadata/tagSchemaRegion/TagSchemaRegion.java
index d1f92538bf..cc611a2c67 100644
--- a/schema-engine-tag/src/main/java/org/apache/iotdb/db/metadata/tagSchemaRegion/TagSchemaRegion.java
+++ b/schema-engine-tag/src/main/java/org/apache/iotdb/db/metadata/tagSchemaRegion/TagSchemaRegion.java
@@ -45,6 +45,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.read.IShowTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.result.ShowTimeSeriesResult;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IActivateTemplateInClusterPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeactivateTemplatePlan;
@@ -342,6 +343,12 @@ public class TagSchemaRegion implements ISchemaRegion {
     throw new UnsupportedOperationException("deleteTimeseriesInBlackList");
   }
 
+  @Override
+  public void createLogicalView(ICreateLogicalViewPlan createLogicalViewPlan)
+      throws MetadataException {
+    throw new UnsupportedOperationException("createLogicalView is unsupported.");
+  }
+
   private List<String> getDevicePaths(List<IDeviceID> deviceIDS) {
     List<String> devicePaths = new ArrayList<>();
     if (config.getDeviceIDTransformationMethod().equals("SHA256")) {
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
index b498e4d145..f175271c40 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
@@ -64,12 +64,16 @@ public class MetadataConstant {
   public static final byte ENTITY_MNODE_TYPE = 3;
   public static final byte STORAGE_GROUP_ENTITY_MNODE_TYPE = 4;
 
+  public static final byte LOGICAL_VIEW_MNODE_TYPE = 5;
+
   public static final String INTERNAL_MNODE_TYPE_NAME = "InternalMNode";
   public static final String STORAGE_GROUP_MNODE_TYPE_NAME = "StorageGroupMNode";
   public static final String MEASUREMENT_MNODE_TYPE_NAME = "MeasurementMNode";
   public static final String ENTITY_MNODE_TYPE_NAME = "EntityMNode";
   public static final String STORAGE_GROUP_ENTITY_MNODE_TYPE_NAME = "StorageGroupEntityMNode";
 
+  public static final String LOGICAL_VIEW_MNODE_TYPE_NAME = "LogicalViewMNode";
+
   public static final String SCHEMA_REGION_METRIC_NAME = "schema_region";
   public static final String SCHEMA_ENGINE_METRIC_NAME = "schema_file";
 
@@ -87,6 +91,8 @@ public class MetadataConstant {
         return ENTITY_MNODE_TYPE_NAME;
       case STORAGE_GROUP_ENTITY_MNODE_TYPE:
         return STORAGE_GROUP_ENTITY_MNODE_TYPE_NAME;
+      case LOGICAL_VIEW_MNODE_TYPE:
+        return LOGICAL_VIEW_MNODE_TYPE_NAME;
       default:
         throw new RuntimeException("Undefined MNode type " + type);
     }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/config/factory/ConfigMNodeFactory.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/config/factory/ConfigMNodeFactory.java
index dc1a03e36b..a1a7611d08 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/config/factory/ConfigMNodeFactory.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/config/factory/ConfigMNodeFactory.java
@@ -18,6 +18,7 @@
  */
 package org.apache.iotdb.db.metadata.mnode.config.factory;
 
+import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
 import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
 import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
 import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -78,4 +79,10 @@ public class ConfigMNodeFactory implements IMNodeFactory<IConfigMNode> {
   public IConfigMNode createInternalMNode(IConfigMNode parent, String name) {
     return new ConfigBasicInternalMNode(parent, name);
   }
+
+  @Override
+  public IMeasurementMNode<IConfigMNode> createLogicalViewMNode(
+      IDeviceMNode<IConfigMNode> parent, String name, IMeasurementInfo measurementInfo) {
+    throw new UnsupportedOperationException();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/factory/MemMNodeFactory.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/factory/MemMNodeFactory.java
index 24215c1e15..1f4e21f7e1 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/factory/MemMNodeFactory.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/factory/MemMNodeFactory.java
@@ -18,6 +18,7 @@
  */
 package org.apache.iotdb.db.metadata.mnode.mem.factory;
 
+import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
 import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
 import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
 import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -28,7 +29,9 @@ import org.apache.iotdb.db.metadata.mnode.mem.impl.BasicInternalMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.impl.DatabaseDeviceMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.impl.DatabaseMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.impl.DeviceMNode;
+import org.apache.iotdb.db.metadata.mnode.mem.impl.LogicalViewMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.impl.MeasurementMNode;
+import org.apache.iotdb.db.metadata.mnode.mem.info.LogicalViewInfo;
 import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 
 public class MemMNodeFactory implements IMNodeFactory<IMemMNode> {
@@ -81,4 +84,15 @@ public class MemMNodeFactory implements IMNodeFactory<IMemMNode> {
   public IMemMNode createInternalMNode(IMemMNode parent, String name) {
     return new BasicInternalMNode(parent, name);
   }
+
+  @Override
+  public IMeasurementMNode<IMemMNode> createLogicalViewMNode(
+      IDeviceMNode<IMemMNode> parent, String name, IMeasurementInfo measurementInfo) {
+    if (measurementInfo instanceof LogicalViewInfo) {
+      return new LogicalViewMNode(
+          parent, name, ((LogicalViewInfo) measurementInfo).getExpression());
+    }
+    throw new UnsupportedOperationException(
+        "createLogicalViewMNode should accept LogicalViewInfo, but got an instance that is not of this type.");
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/LogicalViewMNode.java
similarity index 67%
copy from server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java
copy to server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/LogicalViewMNode.java
index 79e66a366b..b99b829cde 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/LogicalViewMNode.java
@@ -16,25 +16,32 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.iotdb.db.metadata.mnode.mem.impl;
 
 import org.apache.iotdb.commons.schema.node.common.AbstractMeasurementMNode;
+import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
 import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
 import org.apache.iotdb.commons.schema.node.utils.IMNodeContainer;
 import org.apache.iotdb.db.metadata.mnode.mem.IMemMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.basic.BasicMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.container.MemMNodeContainer;
-import org.apache.iotdb.db.metadata.mnode.mem.info.MeasurementInfo;
-import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
+import org.apache.iotdb.db.metadata.mnode.mem.info.LogicalViewInfo;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 
-public class MeasurementMNode extends AbstractMeasurementMNode<IMemMNode, BasicMNode>
+public class LogicalViewMNode extends AbstractMeasurementMNode<IMemMNode, BasicMNode>
     implements IMemMNode {
 
-  public MeasurementMNode(
-      IDeviceMNode<IMemMNode> parent, String name, IMeasurementSchema schema, String alias) {
+  public LogicalViewMNode(
+      IDeviceMNode<IMemMNode> parent, String name, ViewExpression viewExpression) {
     super(
         new BasicMNode(parent == null ? null : parent.getAsMNode(), name),
-        new MeasurementInfo(schema, alias));
+        new LogicalViewInfo(new LogicalViewSchema(name, viewExpression)));
+  }
+
+  @Override
+  public IMNodeContainer<IMemMNode> getChildren() {
+    return MemMNodeContainer.emptyMNodeContainer();
   }
 
   @Override
@@ -42,8 +49,15 @@ public class MeasurementMNode extends AbstractMeasurementMNode<IMemMNode, BasicM
     return this;
   }
 
+  public void setExpression(ViewExpression expression) {
+    IMeasurementInfo measurementInfo = this.getMeasurementInfo();
+    if (measurementInfo instanceof LogicalViewInfo) {
+      ((LogicalViewInfo) measurementInfo).setExpression(expression);
+    }
+  }
+
   @Override
-  public IMNodeContainer<IMemMNode> getChildren() {
-    return MemMNodeContainer.emptyMNodeContainer();
+  public final boolean isLogicalView() {
+    return true;
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/LogicalViewSchema.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/LogicalViewSchema.java
new file mode 100644
index 0000000000..97dd088b1f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/LogicalViewSchema.java
@@ -0,0 +1,215 @@
+/*
+ * 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.metadata.mnode.mem.impl;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.tsfile.encoding.encoder.Encoder;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class LogicalViewSchema
+    implements IMeasurementSchema, Comparable<LogicalViewSchema>, Serializable {
+
+  private String measurementId;
+
+  private ViewExpression expression;
+
+  public LogicalViewSchema(String measurementId, ViewExpression expression) {
+    this.measurementId = measurementId;
+    this.expression = expression;
+  }
+
+  @Override
+  public int compareTo(LogicalViewSchema o) {
+    if (equals(o)) {
+      return 0;
+    } else {
+      return this.measurementId.compareTo(o.measurementId);
+    }
+  }
+
+  @Override
+  public String getMeasurementId() {
+    return this.measurementId;
+  }
+
+  @Override
+  public CompressionType getCompressor() {
+    // TODO: CRTODO:add new CompressionType
+    return CompressionType.UNCOMPRESSED;
+  }
+
+  @Override
+  public TSEncoding getEncodingType() {
+    // TODO: CRTODO: add new TSEncoding
+    return TSEncoding.PLAIN;
+  }
+
+  @Override
+  public TSDataType getType() {
+    // TODO: CRTODO: use a dynamic method to compute data type
+    return TSDataType.BOOLEAN;
+  }
+
+  @Override
+  public byte getTypeInByte() {
+    return TSDataType.BOOLEAN.getType();
+  }
+
+  @Override
+  public void setType(TSDataType dataType) {
+    // do nothing
+  }
+
+  @Override
+  public TSEncoding getTimeTSEncoding() {
+    // TODO: CRTODO: add new TSEncoding
+    return TSEncoding.PLAIN;
+  }
+
+  @Override
+  public Encoder getTimeEncoder() {
+    // TODO: CRTODO: is this ok to return a null value?
+    return null;
+  }
+
+  @Override
+  public Encoder getValueEncoder() {
+    // TODO: CRTODO: is this ok to return a null value?
+    return null;
+  }
+
+  @Override
+  public Map<String, String> getProps() {
+    return new HashMap<>();
+  }
+
+  @Override
+  public List<String> getSubMeasurementsList() {
+    throw new UnsupportedOperationException("unsupported method for LogicalViewSchema");
+  }
+
+  @Override
+  public List<TSDataType> getSubMeasurementsTSDataTypeList() {
+    throw new UnsupportedOperationException("unsupported method for LogicalViewSchema");
+  }
+
+  @Override
+  public List<TSEncoding> getSubMeasurementsTSEncodingList() {
+    throw new UnsupportedOperationException("unsupported method for LogicalViewSchema");
+  }
+
+  @Override
+  public List<Encoder> getSubMeasurementsEncoderList() {
+    throw new UnsupportedOperationException("unsupported method for LogicalViewSchema");
+  }
+
+  @Override
+  public int getSubMeasurementIndex(String measurementId) {
+    return this.measurementId.equals(measurementId) ? 0 : -1;
+  }
+
+  @Override
+  public int getSubMeasurementsCount() {
+    return 1;
+  }
+
+  @Override
+  public boolean containsSubMeasurement(String measurementId) {
+    return this.measurementId.equals(measurementId);
+  }
+
+  // region serialize and deserialize
+
+  @Override
+  public int serializedSize() {
+    throw new RuntimeException(
+        new UnsupportedOperationException(
+            "Can not calculate the size of logical view schema before serializing."));
+  }
+
+  @Override
+  public int serializeTo(ByteBuffer buffer) {
+    // TODO: CRTODO: the size of buffer is not calculated!
+    ReadWriteIOUtils.write(measurementId, buffer);
+
+    ViewExpression.serialize(this.expression, buffer);
+    return 0;
+  }
+
+  @Override
+  public int serializeTo(OutputStream outputStream) throws IOException {
+    // TODO: CRTODO: the size of buffer is not calculated!
+    ReadWriteIOUtils.write(measurementId, outputStream);
+
+    ViewExpression.serialize(this.expression, outputStream);
+    return 0;
+  }
+
+  @Override
+  public int partialSerializeTo(ByteBuffer buffer) {
+    return this.serializeTo(buffer);
+  }
+
+  @Override
+  public int partialSerializeTo(OutputStream outputStream) throws IOException {
+    return this.serializeTo(outputStream);
+  }
+
+  public static LogicalViewSchema deserializeFrom(InputStream inputStream) throws IOException {
+    String measurementId = ReadWriteIOUtils.readString(inputStream);
+
+    ViewExpression expression = ViewExpression.deserialize(inputStream);
+
+    LogicalViewSchema logicalViewSchema = new LogicalViewSchema(measurementId, expression);
+    return logicalViewSchema;
+  }
+
+  public static LogicalViewSchema deserializeFrom(ByteBuffer buffer) throws IOException {
+    String measurementId = ReadWriteIOUtils.readString(buffer);
+
+    ViewExpression expression = ViewExpression.deserialize(buffer);
+
+    LogicalViewSchema logicalViewSchema = new LogicalViewSchema(measurementId, expression);
+    return logicalViewSchema;
+  }
+
+  // endregion
+
+  public ViewExpression getExpression() {
+    return this.expression;
+  }
+
+  public void setExpression(ViewExpression expression) {
+    this.expression = expression;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java
index 79e66a366b..9c3d16adac 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/impl/MeasurementMNode.java
@@ -46,4 +46,9 @@ public class MeasurementMNode extends AbstractMeasurementMNode<IMemMNode, BasicM
   public IMNodeContainer<IMemMNode> getChildren() {
     return MemMNodeContainer.emptyMNodeContainer();
   }
+
+  @Override
+  public final boolean isLogicalView() {
+    return false;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/info/LogicalViewInfo.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/info/LogicalViewInfo.java
new file mode 100644
index 0000000000..e264988aff
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/mem/info/LogicalViewInfo.java
@@ -0,0 +1,161 @@
+/*
+ * 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.metadata.mnode.mem.info;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
+import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
+import org.apache.iotdb.db.metadata.mnode.mem.impl.LogicalViewMNode;
+import org.apache.iotdb.db.metadata.mnode.mem.impl.LogicalViewSchema;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
+
+/**
+ * This structure is used in ViewMNode. It stores all information except the name of this view. The
+ * name of the view is stored by ViewMNode.
+ */
+public class LogicalViewInfo implements IMeasurementInfo {
+
+  /** whether this measurement is pre deleted and considered in black list */
+  private boolean preDeleted = false;
+
+  private LogicalViewSchema schema;
+
+  public LogicalViewInfo(LogicalViewSchema schema) {
+    this.schema = schema;
+  }
+
+  // region logical view interfaces
+  public boolean isAliasSeries() {
+    if (this.getExpression() != null) {
+      if (this.getExpression().isSourceForAliasSeries()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /** @return return the path of alias series if this view is alias series; else return null. */
+  public PartialPath getAliasSeriesPath() {
+    if (this.isAliasSeries()) {
+      if (this.getExpression().getExpressionType() == ViewExpressionType.TIMESERIES) {
+        String pathString = ((TimeSeriesViewOperand) this.getExpression()).getPathString();
+        try {
+          return new PartialPath(pathString);
+        } catch (IllegalPathException e) {
+          throw new RuntimeException(e);
+        }
+      }
+    }
+    return null;
+  }
+
+  public ViewExpression getExpression() {
+    return this.schema.getExpression();
+  }
+
+  public void setExpression(ViewExpression expression) {
+    this.schema.setExpression(expression);
+  }
+  // endregion
+
+  // region IMeasurementInfo interfaces
+
+  @Override
+  public IMeasurementSchema getSchema() {
+    return this.schema;
+  }
+
+  @Override
+  public void setSchema(IMeasurementSchema schema) {
+    this.schema = (LogicalViewSchema) schema;
+  }
+
+  @Override
+  public TSDataType getDataType() {
+    return null;
+  }
+
+  @Override
+  public String getAlias() {
+    return null;
+  }
+
+  @Override
+  public void setAlias(String alias) {
+    // can not set alias for a logical view
+  }
+
+  @Override
+  public long getOffset() {
+    // tag/attribute's start offset in tag file
+    return -1;
+  }
+
+  @Override
+  public void setOffset(long offset) {
+    // can not set offset for a logical view
+  }
+
+  @Override
+  public boolean isPreDeleted() {
+    return this.preDeleted;
+  }
+
+  @Override
+  public void setPreDeleted(boolean preDeleted) {
+    this.preDeleted = preDeleted;
+  }
+
+  /**
+   * The memory occupied by an MeasurementInfo based occupation
+   *
+   * <ol>
+   *   <li>object header, 8B
+   *   <li>boolean preDeleted, 1B
+   *   <li>estimated schema size, 32B
+   *   <li>viewExpression
+   * </ol>
+   */
+  @Override
+  public int estimateSize() {
+    return 8 + 1 + 32 + 64;
+  }
+
+  @Override
+  public void moveDataToNewMNode(IMeasurementMNode<?> newMNode) {
+    // TODO: CRTODO: is this ok for a logical view?
+    if (newMNode instanceof LogicalViewMNode) {
+      LogicalViewMNode logicalViewMNode = (LogicalViewMNode) newMNode;
+      logicalViewMNode.setSchema(this.schema);
+      logicalViewMNode.setPreDeleted(preDeleted);
+      logicalViewMNode.setExpression(this.getExpression());
+    }
+    throw new RuntimeException(
+        new IllegalArgumentException(
+            "Type of newMNode is not LogicalViewMNode! It's "
+                + newMNode.getMNodeType(false).toString()));
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/factory/CacheMNodeFactory.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/factory/CacheMNodeFactory.java
index 5e79e03258..75b99bdf22 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/factory/CacheMNodeFactory.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/factory/CacheMNodeFactory.java
@@ -18,6 +18,7 @@
  */
 package org.apache.iotdb.db.metadata.mnode.schemafile.factory;
 
+import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
 import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
 import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
 import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -81,4 +82,10 @@ public class CacheMNodeFactory implements IMNodeFactory<ICachedMNode> {
   public ICachedMNode createInternalMNode(ICachedMNode parent, String name) {
     return new CachedBasicInternalMNode(parent, name);
   }
+
+  @Override
+  public IMeasurementMNode<ICachedMNode> createLogicalViewMNode(
+      IDeviceMNode<ICachedMNode> parent, String name, IMeasurementInfo measurementInfo) {
+    throw new UnsupportedOperationException();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/impl/CachedMeasurementMNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/impl/CachedMeasurementMNode.java
index df10e21f74..f82c6b1108 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/impl/CachedMeasurementMNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/schemafile/impl/CachedMeasurementMNode.java
@@ -57,4 +57,9 @@ public class CachedMeasurementMNode extends AbstractMeasurementMNode<ICachedMNod
   public IMNodeContainer<ICachedMNode> getChildren() {
     return CachedMNodeContainer.emptyMNodeContainer();
   }
+
+  @Override
+  public final boolean isLogicalView() {
+    return false;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGCachedImpl.java b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGCachedImpl.java
index 92b106e0db..e2c0c65150 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGCachedImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGCachedImpl.java
@@ -66,6 +66,7 @@ import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.utils.Pair;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 
 import org.slf4j.Logger;
@@ -1058,8 +1059,8 @@ public class MTreeBelowSGCachedImpl {
                 return node.getAlias();
               }
 
-              public MeasurementSchema getSchema() {
-                return (MeasurementSchema) node.getSchema();
+              public IMeasurementSchema getSchema() {
+                return node.getSchema();
               }
 
               public Map<String, String> getTags() {
@@ -1080,6 +1081,11 @@ public class MTreeBelowSGCachedImpl {
                 return getParentOfNextMatchedNode().getAsDeviceMNode().isAligned();
               }
 
+              @Override
+              public boolean isLogicalView() {
+                return node.isLogicalView();
+              }
+
               public String getFullPath() {
                 return getPartialPathFromRootToNode(node.getAsMNode()).getFullPath();
               }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
index 8d06137c99..8fb818ca53 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
@@ -42,6 +42,8 @@ import org.apache.iotdb.db.exception.quota.ExceedQuotaException;
 import org.apache.iotdb.db.metadata.MetadataConstant;
 import org.apache.iotdb.db.metadata.mnode.mem.IMemMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.factory.MemMNodeFactory;
+import org.apache.iotdb.db.metadata.mnode.mem.impl.LogicalViewSchema;
+import org.apache.iotdb.db.metadata.mnode.mem.info.LogicalViewInfo;
 import org.apache.iotdb.db.metadata.mtree.store.MemMTreeStore;
 import org.apache.iotdb.db.metadata.mtree.traverser.Traverser;
 import org.apache.iotdb.db.metadata.mtree.traverser.TraverserWithLimitOffsetWrapper;
@@ -64,12 +66,14 @@ import org.apache.iotdb.db.metadata.query.reader.ISchemaReader;
 import org.apache.iotdb.db.metadata.rescon.MemSchemaRegionStatistics;
 import org.apache.iotdb.db.metadata.template.Template;
 import org.apache.iotdb.db.metadata.utils.MetaFormatUtils;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.db.quotas.DataNodeSpaceQuotaManager;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.utils.Pair;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 
 import java.io.File;
@@ -898,8 +902,8 @@ public class MTreeBelowSGMemoryImpl {
                 return node.getAlias();
               }
 
-              public MeasurementSchema getSchema() {
-                return (MeasurementSchema) node.getSchema();
+              public IMeasurementSchema getSchema() {
+                return node.getSchema();
               }
 
               public Map<String, String> getTags() {
@@ -920,6 +924,11 @@ public class MTreeBelowSGMemoryImpl {
                 return getParentOfNextMatchedNode().getAsDeviceMNode().isAligned();
               }
 
+              @Override
+              public boolean isLogicalView() {
+                return node.isLogicalView();
+              }
+
               public String getFullPath() {
                 return getPartialPathFromRootToNode(node.getAsMNode()).getFullPath();
               }
@@ -1000,4 +1009,66 @@ public class MTreeBelowSGMemoryImpl {
     };
   }
   // endregion
+
+  // region interfaces for logical view
+  public IMeasurementMNode<IMemMNode> createLogicalView(
+      PartialPath path, ViewExpression viewExpression) throws MetadataException {
+    // check path
+    String[] nodeNames = path.getNodes();
+    if (nodeNames.length <= 2) {
+      throw new IllegalPathException(path.getFullPath());
+    }
+    MetaFormatUtils.checkTimeseries(path);
+    PartialPath devicePath = path.getDevicePath();
+    IMemMNode deviceParent = checkAndAutoCreateInternalPath(devicePath);
+
+    synchronized (this) {
+      IMemMNode device = checkAndAutoCreateDeviceNode(devicePath.getTailNode(), deviceParent);
+
+      String leafName = path.getMeasurement();
+
+      // no need to check alias, because logical view has no alias
+
+      if (device.hasChild(leafName)) {
+        IMemMNode node = device.getChild(leafName);
+        if (node.isMeasurement()) {
+          if (node.getAsMeasurementMNode().isPreDeleted()) {
+            throw new MeasurementInBlackListException(path);
+          } else {
+            throw new MeasurementAlreadyExistException(
+                path.getFullPath(), node.getAsMeasurementMNode().getMeasurementPath());
+          }
+        } else {
+          throw new PathAlreadyExistException(path.getFullPath());
+        }
+      }
+
+      if (device.isDevice() && device.getAsDeviceMNode().isAligned()) {
+        throw new AlignedTimeseriesException(
+            "timeseries under this entity is aligned, can not create view under this entity.",
+            device.getFullPath());
+      }
+
+      IDeviceMNode<IMemMNode> entityMNode;
+      if (device.isDevice()) {
+        entityMNode = device.getAsDeviceMNode();
+      } else {
+        entityMNode = store.setToEntity(device);
+        if (entityMNode.isDatabase()) {
+          replaceStorageGroupMNode(entityMNode.getAsDatabaseMNode());
+        }
+      }
+
+      IMeasurementMNode<IMemMNode> measurementMNode =
+          nodeFactory.createLogicalViewMNode(
+              entityMNode,
+              leafName,
+              new LogicalViewInfo(new LogicalViewSchema(leafName, viewExpression)));
+
+      store.addChild(entityMNode.getAsMNode(), leafName, measurementMNode.getAsMNode());
+
+      return measurementMNode;
+    }
+  }
+  // endregion
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java
index 7da7632185..6f45ae7baf 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java
@@ -33,6 +33,8 @@ import org.apache.iotdb.commons.schema.node.visitor.MNodeVisitor;
 import org.apache.iotdb.db.metadata.MetadataConstant;
 import org.apache.iotdb.db.metadata.mnode.mem.IMemMNode;
 import org.apache.iotdb.db.metadata.mnode.mem.factory.MemMNodeFactory;
+import org.apache.iotdb.db.metadata.mnode.mem.impl.LogicalViewSchema;
+import org.apache.iotdb.db.metadata.mnode.mem.info.LogicalViewInfo;
 import org.apache.iotdb.db.metadata.mtree.store.MemMTreeStore;
 import org.apache.iotdb.db.metadata.rescon.MemSchemaRegionStatistics;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
@@ -55,6 +57,7 @@ import java.util.function.Consumer;
 
 import static org.apache.iotdb.db.metadata.MetadataConstant.ENTITY_MNODE_TYPE;
 import static org.apache.iotdb.db.metadata.MetadataConstant.INTERNAL_MNODE_TYPE;
+import static org.apache.iotdb.db.metadata.MetadataConstant.LOGICAL_VIEW_MNODE_TYPE;
 import static org.apache.iotdb.db.metadata.MetadataConstant.MEASUREMENT_MNODE_TYPE;
 import static org.apache.iotdb.db.metadata.MetadataConstant.STORAGE_GROUP_ENTITY_MNODE_TYPE;
 import static org.apache.iotdb.db.metadata.MetadataConstant.STORAGE_GROUP_MNODE_TYPE;
@@ -240,6 +243,10 @@ public class MemMTreeSnapshotUtil {
         node = deserializer.deserializeMeasurementMNode(inputStream);
         measurementProcess.accept(node.getAsMeasurementMNode());
         break;
+      case LOGICAL_VIEW_MNODE_TYPE:
+        childrenNum = 0;
+        node = deserializer.deserializeLogicalViewMNode(inputStream);
+        measurementProcess.accept(node.getAsMeasurementMNode());
       default:
         throw new IOException("Unrecognized MNode type " + type);
     }
@@ -327,14 +334,24 @@ public class MemMTreeSnapshotUtil {
     public Boolean visitMeasurementMNode(
         AbstractMeasurementMNode<?, ? extends IMNode<?>> node, OutputStream outputStream) {
       try {
-        ReadWriteIOUtils.write(MEASUREMENT_MNODE_TYPE, outputStream);
-        ReadWriteIOUtils.write(node.getName(), outputStream);
-        node.getSchema().serializeTo(outputStream);
-        ReadWriteIOUtils.write(node.getAlias(), outputStream);
-        ReadWriteIOUtils.write(node.getOffset(), outputStream);
-        ReadWriteIOUtils.write(node.isPreDeleted(), outputStream);
-        return true;
-      } catch (IOException e) {
+        if (node.isMeasurement()) {
+          if (node.isLogicalView()) {
+            ReadWriteIOUtils.write(LOGICAL_VIEW_MNODE_TYPE, outputStream);
+            ReadWriteIOUtils.write(node.getName(), outputStream);
+            node.getSchema().serializeTo(outputStream);
+          } else {
+            ReadWriteIOUtils.write(MEASUREMENT_MNODE_TYPE, outputStream);
+            ReadWriteIOUtils.write(node.getName(), outputStream);
+            node.getSchema().serializeTo(outputStream);
+            ReadWriteIOUtils.write(node.getAlias(), outputStream);
+            ReadWriteIOUtils.write(node.getOffset(), outputStream);
+            ReadWriteIOUtils.write(node.isPreDeleted(), outputStream);
+          }
+          return true;
+        }
+        throw new IllegalArgumentException(
+            "visitMeasurementMNode got unknown node type" + node.getMNodeType(false).toString());
+      } catch (Exception e) {
         logger.error(SERIALIZE_ERROR_INFO, e);
         return false;
       }
@@ -394,5 +411,13 @@ public class MemMTreeSnapshotUtil {
       node.setPreDeleted(ReadWriteIOUtils.readBool(inputStream));
       return node.getAsMNode();
     }
+
+    public IMemMNode deserializeLogicalViewMNode(InputStream inputStream) throws IOException {
+      String name = ReadWriteIOUtils.readString(inputStream);
+      LogicalViewSchema logicalViewSchema = LogicalViewSchema.deserializeFrom(inputStream);
+      IMeasurementMNode<IMemMNode> node =
+          nodeFactory.createLogicalViewMNode(null, name, new LogicalViewInfo(logicalViewSchema));
+      return node.getAsMNode();
+    }
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanType.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanType.java
index e6f0601304..0d36c80161 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanType.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanType.java
@@ -44,6 +44,8 @@ public enum SchemaRegionPlanType {
   PRE_DEACTIVATE_TEMPLATE((byte) 0),
   ROLLBACK_PRE_DEACTIVATE_TEMPLATE((byte) 1),
   DEACTIVATE_TEMPLATE((byte) 2),
+  // logical view
+  CREATE_LOGICAL_VIEW((byte) 66),
 
   // query plan doesn't need any ser/deSer, thus use one type to represent all
   READ_SCHEMA(Byte.MAX_VALUE);
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanVisitor.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanVisitor.java
index 355480f96c..e6d145139a 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/SchemaRegionPlanVisitor.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IAutoCreateDeviceMNo
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeAliasPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeTagOffsetPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeleteTimeSeriesPlan;
@@ -89,4 +90,8 @@ public abstract class SchemaRegionPlanVisitor<R, C> {
   public R visitDeactivateTemplate(IDeactivateTemplatePlan deactivateTemplatePlan, C context) {
     return visitSchemaRegionPlan(deactivateTemplatePlan, context);
   }
+
+  public R visitCreateLogicalView(ICreateLogicalViewPlan createLogicalViewPlan, C context) {
+    return visitSchemaRegionPlan(createLogicalViewPlan, context);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanDeserializer.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanDeserializer.java
index 4fdcd33187..872567109a 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanDeserializer.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanDeserializer.java
@@ -32,6 +32,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IAutoCreateDeviceMNo
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeAliasPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeTagOffsetPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeleteTimeSeriesPlan;
@@ -39,6 +40,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeactivateTempla
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeleteTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IRollbackPreDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IRollbackPreDeleteTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
@@ -337,5 +339,27 @@ public class SchemaRegionPlanDeserializer implements IDeserializer<ISchemaRegion
       }
       return result;
     }
+
+    @Override
+    public ISchemaRegionPlan visitCreateLogicalView(
+        ICreateLogicalViewPlan createLogicalViewPlan, ByteBuffer buffer) {
+
+      int viewSize = buffer.getInt();
+      Map<PartialPath, ViewExpression> viewPathToSourceMap = new HashMap<>();
+      for (int i = 0; i < viewSize; i++) {
+        int byteSizeOfPath = buffer.getInt();
+        byte[] bytesOfPath = new byte[byteSizeOfPath];
+        buffer.get(bytesOfPath);
+        try {
+          PartialPath thisPath = new PartialPath(new String(bytesOfPath));
+          ViewExpression thisExp = ViewExpression.deserialize(buffer);
+          viewPathToSourceMap.put(thisPath, thisExp);
+        } catch (IllegalPathException e) {
+          LOGGER.error("Cannot deserialize SchemaRegionPlan from buffer", e);
+        }
+      }
+      createLogicalViewPlan.setViewPathToSourceExpressionMap(viewPathToSourceMap);
+      return createLogicalViewPlan;
+    }
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanSerializer.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanSerializer.java
index d421211663..afaebf7a32 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanSerializer.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanSerializer.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IAutoCreateDeviceMNo
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeAliasPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeTagOffsetPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeleteTimeSeriesPlan;
@@ -35,6 +36,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeactivateTempla
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeleteTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IRollbackPreDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IRollbackPreDeleteTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
@@ -397,5 +399,30 @@ public class SchemaRegionPlanSerializer implements ISerializer<ISchemaRegionPlan
         }
       }
     }
+
+    @Override
+    public SchemaRegionPlanSerializationResult visitCreateLogicalView(
+        ICreateLogicalViewPlan createLogicalViewPlan, DataOutputStream dataOutputStream) {
+      try {
+        int viewSize = createLogicalViewPlan.getViewSize();
+        // serialize size of views
+        dataOutputStream.writeInt(viewSize);
+        List<PartialPath> viewPAthList = createLogicalViewPlan.getViewPathList();
+        Map<PartialPath, ViewExpression> viewPathToSourceMap =
+            createLogicalViewPlan.getViewPathToSourceExpressionMap();
+        for (int i = 0; i < viewSize; i++) {
+          PartialPath thisPath = viewPAthList.get(i);
+          ViewExpression thisExp = viewPathToSourceMap.get(thisPath);
+          // for each view, serialize info of it
+          byte[] bytes = thisPath.getFullPath().getBytes();
+          dataOutputStream.writeInt(bytes.length);
+          dataOutputStream.write(bytes);
+          ViewExpression.serialize(thisExp, dataOutputStream);
+        }
+        return SchemaRegionPlanSerializationResult.SUCCESS;
+      } catch (IOException e) {
+        return new SchemaRegionPlanSerializationResult(e);
+      }
+    }
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanTxtSerializer.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanTxtSerializer.java
index c820f0db95..5cbf7b6eb6 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanTxtSerializer.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/SchemaRegionPlanTxtSerializer.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IAutoCreateDeviceMNo
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeAliasPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeTagOffsetPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeleteTimeSeriesPlan;
@@ -35,6 +36,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeactivateTempla
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeleteTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IRollbackPreDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IRollbackPreDeleteTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
@@ -240,5 +242,24 @@ public class SchemaRegionPlanTxtSerializer implements ISerializer<ISchemaRegionP
       templateSetInfo.forEach((k, v) -> stringBuilder.append(k).append(": ").append(v).append(";"));
       stringBuilder.append("}");
     }
+
+    @Override
+    public Void visitCreateLogicalView(
+        ICreateLogicalViewPlan createLogicalViewPlan, StringBuilder stringBuilder) {
+      int viewSize = createLogicalViewPlan.getViewSize();
+      List<PartialPath> viewPathList = createLogicalViewPlan.getViewPathList();
+      Map<PartialPath, ViewExpression> viewPathToSourceMap =
+          createLogicalViewPlan.getViewPathToSourceExpressionMap();
+      for (int i = 0; i < viewSize; i++) {
+        PartialPath thisPath = viewPathList.get(i);
+        ViewExpression thisExp = viewPathToSourceMap.get(thisPath);
+        stringBuilder.append(thisPath).append(FIELD_SEPARATOR).append(thisExp.toString());
+        if (i + 1 >= viewSize) {
+          break;
+        }
+        stringBuilder.append(FIELD_SEPARATOR);
+      }
+      return null;
+    }
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/write/CreateLogicalViewPlanImpl.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/write/CreateLogicalViewPlanImpl.java
new file mode 100644
index 0000000000..f871cb54b5
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/impl/write/CreateLogicalViewPlanImpl.java
@@ -0,0 +1,75 @@
+/*
+ * 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.metadata.plan.schemaregion.impl.write;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CreateLogicalViewPlanImpl implements ICreateLogicalViewPlan {
+
+  private PartialPath targetPath;
+  private ViewExpression sourceExpression;
+
+  public CreateLogicalViewPlanImpl(PartialPath targetPath, ViewExpression sourceExpression) {
+    this.targetPath = targetPath;
+    this.sourceExpression = sourceExpression;
+  }
+
+  @Override
+  public int getViewSize() {
+    return 1;
+  }
+
+  @Override
+  public Map<PartialPath, ViewExpression> getViewPathToSourceExpressionMap() {
+    Map<PartialPath, ViewExpression> result = new HashMap<>();
+    result.put(this.targetPath, this.sourceExpression);
+    return result;
+  }
+
+  @Override
+  public List<PartialPath> getViewPathList() {
+    return Collections.singletonList(this.targetPath);
+  }
+
+  @Override
+  public void setViewPathToSourceExpressionMap(
+      Map<PartialPath, ViewExpression> viewPathToSourceExpressionMap) {
+    for (Map.Entry<PartialPath, ViewExpression> entry : viewPathToSourceExpressionMap.entrySet()) {
+      this.targetPath = entry.getKey();
+      this.sourceExpression = entry.getValue();
+      break;
+    }
+  }
+
+  public PartialPath getTargetPath() {
+    return this.targetPath;
+  }
+
+  public ViewExpression getSourceExpression() {
+    return this.sourceExpression;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/result/ShowTimeSeriesResult.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/result/ShowTimeSeriesResult.java
index bbd5065166..37512da58c 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/result/ShowTimeSeriesResult.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/result/ShowTimeSeriesResult.java
@@ -18,11 +18,12 @@
  */
 package org.apache.iotdb.db.metadata.plan.schemaregion.result;
 
+import org.apache.iotdb.db.metadata.mnode.mem.impl.LogicalViewSchema;
 import org.apache.iotdb.db.metadata.query.info.ITimeSeriesSchemaInfo;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 
 import java.util.Map;
 import java.util.Objects;
@@ -31,7 +32,7 @@ public class ShowTimeSeriesResult extends ShowSchemaResult implements ITimeSerie
 
   private String alias;
 
-  private MeasurementSchema measurementSchema;
+  private IMeasurementSchema measurementSchema;
 
   private Map<String, String> tags;
   private Map<String, String> attributes;
@@ -41,7 +42,7 @@ public class ShowTimeSeriesResult extends ShowSchemaResult implements ITimeSerie
   public ShowTimeSeriesResult(
       String name,
       String alias,
-      MeasurementSchema measurementSchema,
+      IMeasurementSchema measurementSchema,
       Map<String, String> tags,
       Map<String, String> attributes,
       boolean isUnderAlignedDevice) {
@@ -62,7 +63,7 @@ public class ShowTimeSeriesResult extends ShowSchemaResult implements ITimeSerie
   }
 
   @Override
-  public MeasurementSchema getSchema() {
+  public IMeasurementSchema getSchema() {
     return measurementSchema;
   }
 
@@ -81,6 +82,11 @@ public class ShowTimeSeriesResult extends ShowSchemaResult implements ITimeSerie
     return isUnderAlignedDevice;
   }
 
+  @Override
+  public boolean isLogicalView() {
+    return this.measurementSchema instanceof LogicalViewSchema;
+  }
+
   public TSDataType getDataType() {
     return measurementSchema.getType();
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/write/ICreateLogicalViewPlan.java b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/write/ICreateLogicalViewPlan.java
new file mode 100644
index 0000000000..33c6a399fb
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/plan/schemaregion/write/ICreateLogicalViewPlan.java
@@ -0,0 +1,66 @@
+/*
+ * 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.metadata.plan.schemaregion.write;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.metadata.plan.schemaregion.ISchemaRegionPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.SchemaRegionPlanType;
+import org.apache.iotdb.db.metadata.plan.schemaregion.SchemaRegionPlanVisitor;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+
+import java.util.List;
+import java.util.Map;
+
+public interface ICreateLogicalViewPlan extends ISchemaRegionPlan {
+  @Override
+  default SchemaRegionPlanType getPlanType() {
+    return SchemaRegionPlanType.CREATE_LOGICAL_VIEW;
+  }
+
+  @Override
+  default <R, C> R accept(SchemaRegionPlanVisitor<R, C> visitor, C context) {
+    return visitor.visitCreateLogicalView(this, context);
+  }
+
+  /**
+   * Get how many views will be created.
+   *
+   * @return the number of views that will be created
+   */
+  int getViewSize();
+
+  /** @return return a map, from view path (the targets) to source expression. */
+  Map<PartialPath, ViewExpression> getViewPathToSourceExpressionMap();
+
+  /** @return return a list of target paths (paths of views). */
+  List<PartialPath> getViewPathList();
+
+  /**
+   * @param viewPathToSourceExpressionMap a map from view path (the targets) to source expression.
+   */
+  void setViewPathToSourceExpressionMap(
+      Map<PartialPath, ViewExpression> viewPathToSourceExpressionMap);
+
+  //  /**
+  //   * @param partialPaths a list of partialPaths. Will be transformed into expressions then set
+  // as source. (source timeseries or expressions in query statement)
+  //   */
+  //  void setSourceByPartialPath(List<PartialPath> partialPaths);
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java b/server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java
index 94f487a917..577d5f49b3 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.db.metadata.query.info;
 
-import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 
 import java.util.Map;
 
@@ -27,11 +27,13 @@ public interface ITimeSeriesSchemaInfo extends ISchemaInfo {
 
   String getAlias();
 
-  MeasurementSchema getSchema();
+  IMeasurementSchema getSchema();
 
   Map<String, String> getTags();
 
   Map<String, String> getAttributes();
 
   boolean isUnderAlignedDevice();
+
+  boolean isLogicalView();
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/ISchemaRegion.java b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/ISchemaRegion.java
index 97febd7ce5..1dcac009dc 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/ISchemaRegion.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/ISchemaRegion.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.read.IShowNodesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.read.IShowTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IActivateTemplateInClusterPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IPreDeactivateTemplatePlan;
@@ -162,6 +163,10 @@ public interface ISchemaRegion {
   void deleteTimeseriesInBlackList(PathPatternTree patternTree) throws MetadataException;
   // endregion
 
+  // region Interfaces for Logical View
+  void createLogicalView(ICreateLogicalViewPlan createLogicalViewPlan) throws MetadataException;
+  // endregion
+
   // region Interfaces for metadata info Query
 
   // region Interfaces for timeseries, measurement and schema info Query
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
index bdd8300746..d511c34ee9 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
@@ -60,6 +60,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IAutoCreateDeviceMNo
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeAliasPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeTagOffsetPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeleteTimeSeriesPlan;
@@ -74,6 +75,7 @@ import org.apache.iotdb.db.metadata.query.reader.ISchemaReader;
 import org.apache.iotdb.db.metadata.rescon.MemSchemaRegionStatistics;
 import org.apache.iotdb.db.metadata.tag.TagManager;
 import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.db.utils.SchemaUtils;
 import org.apache.iotdb.external.api.ISeriesNumerMonitor;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -781,6 +783,44 @@ public class SchemaRegionMemoryImpl implements ISchemaRegion {
     }
   }
 
+  @Override
+  public void createLogicalView(ICreateLogicalViewPlan plan) throws MetadataException {
+    if (!regionStatistics.isAllowToCreateNewSeries()) {
+      throw new SeriesOverflowException();
+    }
+
+    try {
+      List<PartialPath> pathList = plan.getViewPathList();
+      Map<PartialPath, ViewExpression> viewPathToSourceMap =
+          plan.getViewPathToSourceExpressionMap();
+      for (PartialPath path : pathList) {
+        try {
+          if (seriesNumberMonitor != null && !seriesNumberMonitor.addTimeSeries(1)) {
+            throw new SeriesNumberOverflowException();
+          }
+
+          // create one logical view
+          IMeasurementMNode<IMemMNode> leafMNode;
+          leafMNode = mtree.createLogicalView(path, viewPathToSourceMap.get(path));
+        } catch (Throwable t) {
+          if (seriesNumberMonitor != null) {
+            seriesNumberMonitor.deleteTimeSeries(1);
+          }
+          throw t;
+        }
+      }
+      // write log
+      if (!isRecovering) {
+        writeToMLog(plan);
+      }
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+    // update statistics
+    regionStatistics.addTimeseries(1L);
+    // TODO: CRTODO: shall we update id table?
+  }
+
   private void deleteSingleTimeseriesInBlackList(PartialPath path)
       throws MetadataException, IOException {
     IMeasurementMNode<IMemMNode> measurementMNode = mtree.deleteTimeseries(path);
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionSchemaFileImpl.java b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionSchemaFileImpl.java
index 522c4e87e0..f54068f4de 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionSchemaFileImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionSchemaFileImpl.java
@@ -63,6 +63,7 @@ import org.apache.iotdb.db.metadata.plan.schemaregion.write.IAutoCreateDeviceMNo
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeAliasPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IChangeTagOffsetPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeactivateTemplatePlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.IDeleteTimeSeriesPlan;
@@ -891,6 +892,12 @@ public class SchemaRegionSchemaFileImpl implements ISchemaRegion {
     }
   }
 
+  @Override
+  public void createLogicalView(ICreateLogicalViewPlan createLogicalViewPlan)
+      throws MetadataException {
+    throw new UnsupportedOperationException("createLogicalView is unsupported.");
+  }
+
   private void deleteSingleTimeseriesInBlackList(PartialPath path)
       throws MetadataException, IOException {
     IMeasurementMNode<ICachedMNode> measurementMNode = mtree.deleteTimeseries(path);
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ViewExpression.java
new file mode 100644
index 0000000000..9a37eff104
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ViewExpression.java
@@ -0,0 +1,318 @@
+/*
+ * 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.metadata.view.viewExpression;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.AdditionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.DivisionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.ModuloViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.MultiplicationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.SubtractionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.EqualToViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.NonEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicAndViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicOrViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.ConstantViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.NullViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimestampViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.multi.FunctionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.BetweenViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.InViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.IsNullViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LikeViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LogicNotViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.NegationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.RegularViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * This is a class designed for views, such as logical views. The view expression is a simple sketch
+ * of an expression. A view expression stores less information, that make it easier to store and
+ * serialize.
+ *
+ * <p>A view expression has to be transformed into expression in same type before analyzing. Also,
+ * an expression should be transformed into view expression before storage in views.
+ */
+public abstract class ViewExpression {
+
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitExpression(this, context);
+  }
+
+  public abstract ViewExpressionType getExpressionType();
+
+  /** @return if this view expression is a leaf node, return true; else return false. */
+  public final boolean isLeafOperand() {
+    return isLeafOperandInternal();
+  }
+
+  protected abstract boolean isLeafOperandInternal();
+
+  /**
+   * @return return the DIRECT children view expressions if it has any, otherwise an EMPTY list will
+   *     be returned
+   */
+  public abstract List<ViewExpression> getChildViewExpressions();
+
+  /**
+   * @return if this view expression could be a source for an ALIAS series (one kind of view),
+   *     return true; else return false. Foe example, a SINGLE TimeSeriesOperand could be a source
+   *     for an alias view.
+   */
+  public final boolean isSourceForAliasSeries() {
+    if (this.getExpressionType().getExpressionTypeInShortEnum()
+        == ViewExpressionType.TIMESERIES.getExpressionTypeInShortEnum()) {
+      return true;
+    }
+    return false;
+  }
+
+  public String toString() {
+    return this.toString(true);
+  }
+
+  public abstract String toString(boolean isRoot);
+
+  // region methods for serializing and deserializing
+  protected abstract void serialize(ByteBuffer byteBuffer);
+
+  protected abstract void serialize(OutputStream stream) throws IOException;
+
+  public static void serialize(ViewExpression expression, ByteBuffer byteBuffer) {
+    ReadWriteIOUtils.write(
+        expression.getExpressionType().getExpressionTypeInShortEnum(), byteBuffer);
+
+    expression.serialize(byteBuffer);
+  }
+
+  public static void serialize(ViewExpression expression, OutputStream stream) throws IOException {
+    ReadWriteIOUtils.write(expression.getExpressionType().getExpressionTypeInShortEnum(), stream);
+
+    expression.serialize(stream);
+  }
+
+  public static ViewExpression deserialize(ByteBuffer byteBuffer) {
+    short type = ReadWriteIOUtils.readShort(byteBuffer);
+
+    ViewExpression expression;
+    switch (type) {
+      case -4:
+        expression = new ConstantViewOperand(byteBuffer);
+      case -3:
+        expression = new TimestampViewOperand(byteBuffer);
+        break;
+      case -2:
+        expression = new TimeSeriesViewOperand(byteBuffer);
+        break;
+      case -1:
+        expression = new FunctionViewExpression(byteBuffer);
+        break;
+
+      case 0:
+        expression = new NegationViewExpression(byteBuffer);
+        break;
+      case 1:
+        expression = new LogicNotViewExpression(byteBuffer);
+        break;
+
+      case 2:
+        expression = new MultiplicationViewExpression(byteBuffer);
+        break;
+      case 3:
+        expression = new DivisionViewExpression(byteBuffer);
+        break;
+      case 4:
+        expression = new ModuloViewExpression(byteBuffer);
+        break;
+
+      case 5:
+        expression = new AdditionViewExpression(byteBuffer);
+        break;
+      case 6:
+        expression = new SubtractionViewExpression(byteBuffer);
+        break;
+
+      case 7:
+        expression = new EqualToViewExpression(byteBuffer);
+        break;
+      case 8:
+        expression = new NonEqualViewExpression(byteBuffer);
+        break;
+      case 9:
+        expression = new GreaterEqualViewExpression(byteBuffer);
+        break;
+      case 10:
+        expression = new GreaterThanViewExpression(byteBuffer);
+        break;
+      case 11:
+        expression = new LessEqualViewExpression(byteBuffer);
+        break;
+      case 12:
+        expression = new LessThanViewExpression(byteBuffer);
+        break;
+
+      case 13:
+        expression = new LikeViewExpression(byteBuffer);
+        break;
+      case 14:
+        expression = new RegularViewExpression(byteBuffer);
+        break;
+
+      case 15:
+        expression = new IsNullViewExpression(byteBuffer);
+        break;
+
+      case 16:
+        expression = new BetweenViewExpression(byteBuffer);
+        break;
+
+      case 17:
+        expression = new InViewExpression(byteBuffer);
+        break;
+
+      case 18:
+        expression = new LogicAndViewExpression(byteBuffer);
+        break;
+
+      case 19:
+        expression = new LogicOrViewExpression(byteBuffer);
+        break;
+
+      case 20:
+        expression = new NullViewOperand();
+        break;
+      default:
+        throw new IllegalArgumentException("Invalid viewExpression type: " + type);
+    }
+    return expression;
+  }
+
+  public static ViewExpression deserialize(InputStream inputStream) {
+    try {
+      short type = ReadWriteIOUtils.readShort(inputStream);
+
+      ViewExpression expression;
+      switch (type) {
+        case -4:
+          expression = new ConstantViewOperand(inputStream);
+        case -3:
+          expression = new TimestampViewOperand(inputStream);
+          break;
+        case -2:
+          expression = new TimeSeriesViewOperand(inputStream);
+          break;
+        case -1:
+          expression = new FunctionViewExpression(inputStream);
+          break;
+
+        case 0:
+          expression = new NegationViewExpression(inputStream);
+          break;
+        case 1:
+          expression = new LogicNotViewExpression(inputStream);
+          break;
+
+        case 2:
+          expression = new MultiplicationViewExpression(inputStream);
+          break;
+        case 3:
+          expression = new DivisionViewExpression(inputStream);
+          break;
+        case 4:
+          expression = new ModuloViewExpression(inputStream);
+          break;
+
+        case 5:
+          expression = new AdditionViewExpression(inputStream);
+          break;
+        case 6:
+          expression = new SubtractionViewExpression(inputStream);
+          break;
+
+        case 7:
+          expression = new EqualToViewExpression(inputStream);
+          break;
+        case 8:
+          expression = new NonEqualViewExpression(inputStream);
+          break;
+        case 9:
+          expression = new GreaterEqualViewExpression(inputStream);
+          break;
+        case 10:
+          expression = new GreaterThanViewExpression(inputStream);
+          break;
+        case 11:
+          expression = new LessEqualViewExpression(inputStream);
+          break;
+        case 12:
+          expression = new LessThanViewExpression(inputStream);
+          break;
+
+        case 13:
+          expression = new LikeViewExpression(inputStream);
+          break;
+        case 14:
+          expression = new RegularViewExpression(inputStream);
+          break;
+
+        case 15:
+          expression = new IsNullViewExpression(inputStream);
+          break;
+
+        case 16:
+          expression = new BetweenViewExpression(inputStream);
+          break;
+
+        case 17:
+          expression = new InViewExpression(inputStream);
+          break;
+
+        case 18:
+          expression = new LogicAndViewExpression(inputStream);
+          break;
+
+        case 19:
+          expression = new LogicOrViewExpression(inputStream);
+          break;
+
+        case 20:
+          expression = new NullViewOperand();
+          break;
+        default:
+          throw new IllegalArgumentException("Invalid viewExpression type: " + type);
+      }
+      return expression;
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // end region
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ViewExpressionType.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ViewExpressionType.java
new file mode 100644
index 0000000000..a0134f27eb
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ViewExpressionType.java
@@ -0,0 +1,76 @@
+/*
+ * 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.metadata.view.viewExpression;
+
+public enum ViewExpressionType {
+  CONSTANT((short) -4, (short) 1400),
+  TIMESTAMP((short) -3, (short) 1300),
+  TIMESERIES((short) -2, (short) 1200),
+  FUNCTION((short) -1, (short) 1100),
+
+  NEGATION((short) 0, (short) 1000),
+  LOGIC_NOT((short) 1, (short) 1000),
+
+  MULTIPLICATION((short) 2, (short) 900),
+  DIVISION((short) 3, (short) 900),
+  MODULO((short) 4, (short) 900),
+
+  ADDITION((short) 5, (short) 800),
+  SUBTRACTION((short) 6, (short) 800),
+
+  EQUAL_TO((short) 7, (short) 600),
+  NON_EQUAL((short) 8, (short) 600),
+  GREATER_EQUAL((short) 9, (short) 600),
+  GREATER_THAN((short) 10, (short) 600),
+  LESS_EQUAL((short) 11, (short) 600),
+  LESS_THAN((short) 12, (short) 600),
+
+  LIKE((short) 13, (short) 500),
+  REGEXP((short) 14, (short) 500),
+
+  IS_NULL((short) 15, (short) 475),
+
+  BETWEEN((short) 16, (short) 450),
+
+  IN((short) 17, (short) 400),
+
+  LOGIC_AND((short) 18, (short) 300),
+
+  LOGIC_OR((short) 19, (short) 200),
+
+  NULL((short) 20, (short) 1400),
+  ;
+
+  private final short expressionType;
+  private final short priority;
+
+  ViewExpressionType(short expressionType, short priority) {
+    this.expressionType = expressionType;
+    this.priority = priority;
+  }
+
+  public short getExpressionTypeInShortEnum() {
+    return expressionType;
+  }
+
+  public short getPriority() {
+    return priority;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/BinaryViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/BinaryViewExpression.java
new file mode 100644
index 0000000000..a4c660804f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/BinaryViewExpression.java
@@ -0,0 +1,119 @@
+/*
+ * 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.metadata.view.viewExpression.binary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class BinaryViewExpression extends ViewExpression {
+
+  // region member variables and init functions
+  protected ViewExpression leftExpression;
+  protected ViewExpression rightExpression;
+
+  protected BinaryViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    this.leftExpression = leftExpression;
+    this.rightExpression = rightExpression;
+  }
+
+  protected BinaryViewExpression(ByteBuffer byteBuffer) {
+    this.leftExpression = ViewExpression.deserialize(byteBuffer);
+    this.rightExpression = ViewExpression.deserialize(byteBuffer);
+  }
+
+  protected BinaryViewExpression(InputStream inputStream) {
+    this.leftExpression = ViewExpression.deserialize(inputStream);
+    this.rightExpression = ViewExpression.deserialize(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitBinaryExpression(this, context);
+  }
+
+  @Override
+  protected final boolean isLeafOperandInternal() {
+    return false;
+  }
+
+  @Override
+  public final List<ViewExpression> getChildViewExpressions() {
+    return Arrays.asList(leftExpression, rightExpression);
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    ViewExpression.serialize(leftExpression, byteBuffer);
+    ViewExpression.serialize(rightExpression, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    ViewExpression.serialize(leftExpression, stream);
+    ViewExpression.serialize(rightExpression, stream);
+  }
+  // endregion
+  public void setLeftExpression(ViewExpression leftExpression) {
+    this.leftExpression = leftExpression;
+  }
+
+  public void setRightExpression(ViewExpression rightExpression) {
+    this.rightExpression = rightExpression;
+  }
+
+  public ViewExpression getLeftExpression() {
+    return leftExpression;
+  }
+
+  public ViewExpression getRightExpression() {
+    return rightExpression;
+  }
+
+  public abstract String getStringSymbol();
+
+  @Override
+  public String toString() {
+    return this.toString(true);
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    String basicString =
+        leftExpression.toString(false)
+            + " "
+            + this.getStringSymbol()
+            + " "
+            + rightExpression.toString(false);
+    if (isRoot) {
+      return basicString;
+    } else {
+      return "(" + basicString + ")";
+    }
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/AdditionViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/AdditionViewExpression.java
new file mode 100644
index 0000000000..40aeffe364
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/AdditionViewExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.binary.arithmetic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class AdditionViewExpression extends ArithmeticBinaryViewExpression {
+
+  // region member variables and init functions
+  public AdditionViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public AdditionViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public AdditionViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitAdditionExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "+";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.ADDITION;
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/ArithmeticBinaryViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/ArithmeticBinaryViewExpression.java
new file mode 100644
index 0000000000..24b7a44178
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/ArithmeticBinaryViewExpression.java
@@ -0,0 +1,52 @@
+/*
+ * 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.metadata.view.viewExpression.binary.arithmetic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.BinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public abstract class ArithmeticBinaryViewExpression extends BinaryViewExpression {
+
+  // region member variables and init functions
+  protected ArithmeticBinaryViewExpression(
+      ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  protected ArithmeticBinaryViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  protected ArithmeticBinaryViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitArithmeticBinaryExpression(this, context);
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/DivisionViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/DivisionViewExpression.java
new file mode 100644
index 0000000000..cf43cd44e1
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/DivisionViewExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.binary.arithmetic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class DivisionViewExpression extends ArithmeticBinaryViewExpression {
+
+  // region member variables and init functions
+  public DivisionViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public DivisionViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public DivisionViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitDivisionExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "/";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.DIVISION;
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/ModuloViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/ModuloViewExpression.java
new file mode 100644
index 0000000000..fe569255cc
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/ModuloViewExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.binary.arithmetic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class ModuloViewExpression extends ArithmeticBinaryViewExpression {
+
+  // region member variables and init functions
+  public ModuloViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public ModuloViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public ModuloViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitModuloExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "%";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.MODULO;
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/MultiplicationViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/MultiplicationViewExpression.java
new file mode 100644
index 0000000000..ea6e6b50de
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/MultiplicationViewExpression.java
@@ -0,0 +1,63 @@
+/*
+ * 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.metadata.view.viewExpression.binary.arithmetic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class MultiplicationViewExpression extends ArithmeticBinaryViewExpression {
+
+  // region member variables and init functions
+  public MultiplicationViewExpression(
+      ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public MultiplicationViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public MultiplicationViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitMultiplicationExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "*";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.MULTIPLICATION;
+  }
+  // endregion
+
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/SubtractionViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/SubtractionViewExpression.java
new file mode 100644
index 0000000000..08097e60d9
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/arithmetic/SubtractionViewExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.binary.arithmetic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class SubtractionViewExpression extends ArithmeticBinaryViewExpression {
+
+  // region member variables and init functions
+  public SubtractionViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public SubtractionViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public SubtractionViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitSubtractionExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "-";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.SUBTRACTION;
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/CompareBinaryViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/CompareBinaryViewExpression.java
new file mode 100644
index 0000000000..64da03ad30
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/CompareBinaryViewExpression.java
@@ -0,0 +1,52 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.BinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public abstract class CompareBinaryViewExpression extends BinaryViewExpression {
+
+  // region member variables and init functions
+  protected CompareBinaryViewExpression(
+      ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  protected CompareBinaryViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  protected CompareBinaryViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitCompareBinaryExpression(this, context);
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/EqualToViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/EqualToViewExpression.java
new file mode 100644
index 0000000000..9a76d16e23
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/EqualToViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class EqualToViewExpression extends CompareBinaryViewExpression {
+
+  public EqualToViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public EqualToViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public EqualToViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitEqualToExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "==";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.EQUAL_TO;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/GreaterEqualViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/GreaterEqualViewExpression.java
new file mode 100644
index 0000000000..90c79baff9
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/GreaterEqualViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class GreaterEqualViewExpression extends CompareBinaryViewExpression {
+
+  public GreaterEqualViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public GreaterEqualViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public GreaterEqualViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitGreaterEqualExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return ">=";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.GREATER_EQUAL;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/GreaterThanViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/GreaterThanViewExpression.java
new file mode 100644
index 0000000000..1e371516c6
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/GreaterThanViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class GreaterThanViewExpression extends CompareBinaryViewExpression {
+
+  public GreaterThanViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public GreaterThanViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public GreaterThanViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitGreaterThanExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return ">";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.GREATER_THAN;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/LessEqualViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/LessEqualViewExpression.java
new file mode 100644
index 0000000000..e3ea2efe28
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/LessEqualViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class LessEqualViewExpression extends CompareBinaryViewExpression {
+
+  public LessEqualViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public LessEqualViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public LessEqualViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLessEqualExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "<=";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.LESS_EQUAL;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/LessThanViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/LessThanViewExpression.java
new file mode 100644
index 0000000000..7b3b1f8436
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/LessThanViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class LessThanViewExpression extends CompareBinaryViewExpression {
+
+  public LessThanViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public LessThanViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public LessThanViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLessThanExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "<";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.LESS_THAN;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/NonEqualViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/NonEqualViewExpression.java
new file mode 100644
index 0000000000..5627912cc7
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/compare/NonEqualViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.compare;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class NonEqualViewExpression extends CompareBinaryViewExpression {
+
+  public NonEqualViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public NonEqualViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public NonEqualViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitNonEqualExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "!=";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.NON_EQUAL;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicAndViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicAndViewExpression.java
new file mode 100644
index 0000000000..077ef3acc5
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicAndViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.logic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class LogicAndViewExpression extends LogicBinaryViewExpression {
+
+  public LogicAndViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public LogicAndViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public LogicAndViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLogicAndExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "AND";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.LOGIC_AND;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicBinaryViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicBinaryViewExpression.java
new file mode 100644
index 0000000000..3b48ea7140
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicBinaryViewExpression.java
@@ -0,0 +1,52 @@
+/*
+ * 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.metadata.view.viewExpression.binary.logic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.BinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public abstract class LogicBinaryViewExpression extends BinaryViewExpression {
+
+  // region member variables and init functions
+  protected LogicBinaryViewExpression(
+      ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  protected LogicBinaryViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  protected LogicBinaryViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLogicBinaryExpression(this, context);
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicOrViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicOrViewExpression.java
new file mode 100644
index 0000000000..4791d29d1f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/binary/logic/LogicOrViewExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.metadata.view.viewExpression.binary.logic;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class LogicOrViewExpression extends LogicBinaryViewExpression {
+
+  public LogicOrViewExpression(ViewExpression leftExpression, ViewExpression rightExpression) {
+    super(leftExpression, rightExpression);
+  }
+
+  public LogicOrViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+  }
+
+  public LogicOrViewExpression(InputStream inputStream) {
+    super(inputStream);
+  }
+
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLogicOrExpression(this, context);
+  }
+
+  @Override
+  public String getStringSymbol() {
+    return "OR";
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.LOGIC_OR;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/ConstantViewOperand.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/ConstantViewOperand.java
new file mode 100644
index 0000000000..7e727c25fa
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/ConstantViewOperand.java
@@ -0,0 +1,98 @@
+/*
+ * 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.metadata.view.viewExpression.leaf;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import org.apache.commons.lang3.Validate;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class ConstantViewOperand extends LeafViewOperand {
+
+  // region member variables and init functions
+  private final String valueString;
+  private final TSDataType dataType;
+
+  public ConstantViewOperand(TSDataType dataType, String valueString) {
+    this.dataType = Validate.notNull(dataType);
+    this.valueString = Validate.notNull(valueString);
+  }
+
+  public ConstantViewOperand(ByteBuffer byteBuffer) {
+    dataType = TSDataType.deserializeFrom(byteBuffer);
+    valueString = ReadWriteIOUtils.readString(byteBuffer);
+  }
+
+  public ConstantViewOperand(InputStream inputStream) {
+    try {
+      dataType = TSDataType.deserialize(ReadWriteIOUtils.readByte(inputStream));
+      valueString = ReadWriteIOUtils.readString(inputStream);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitConstantOperand(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.CONSTANT;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return this.valueString;
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    dataType.serializeTo(byteBuffer);
+    ReadWriteIOUtils.write(valueString, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    stream.write(dataType.serialize());
+    ReadWriteIOUtils.write(valueString, stream);
+  }
+
+  // endregion
+
+  public TSDataType getDataType() {
+    return dataType;
+  }
+
+  public String getValueString() {
+    return valueString;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/LeafViewOperand.java
similarity index 59%
copy from server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java
copy to server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/LeafViewOperand.java
index 94f487a917..127306f284 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/query/info/ITimeSeriesSchemaInfo.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/LeafViewOperand.java
@@ -7,7 +7,7 @@
  * "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
+ *     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
@@ -17,21 +17,23 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.metadata.query.info;
+package org.apache.iotdb.db.metadata.view.viewExpression.leaf;
 
-import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
 
-public interface ITimeSeriesSchemaInfo extends ISchemaInfo {
+public abstract class LeafViewOperand extends ViewExpression {
 
-  String getAlias();
+  @Override
+  protected final boolean isLeafOperandInternal() {
+    return true;
+  }
 
-  MeasurementSchema getSchema();
-
-  Map<String, String> getTags();
-
-  Map<String, String> getAttributes();
-
-  boolean isUnderAlignedDevice();
+  @Override
+  public final List<ViewExpression> getChildViewExpressions() {
+    // leaf node has no child nodes.
+    return new ArrayList<>();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/NullViewOperand.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/NullViewOperand.java
new file mode 100644
index 0000000000..a62e94e4b0
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/NullViewOperand.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.leaf;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class NullViewOperand extends LeafViewOperand {
+
+  // region member variables and init functions
+  public NullViewOperand() {};
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitNullOperand(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.NULL;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return "null";
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    // do nothing
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    // do nothing
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/TimeSeriesViewOperand.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/TimeSeriesViewOperand.java
new file mode 100644
index 0000000000..c34aefdac3
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/TimeSeriesViewOperand.java
@@ -0,0 +1,87 @@
+/*
+ * 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.metadata.view.viewExpression.leaf;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class TimeSeriesViewOperand extends LeafViewOperand {
+
+  // region member variables and init functions
+  private String pathString;
+
+  public TimeSeriesViewOperand(String path) {
+    this.pathString = path;
+  }
+
+  public TimeSeriesViewOperand(ByteBuffer byteBuffer) {
+    this.pathString = ReadWriteIOUtils.readString(byteBuffer);
+  }
+
+  public TimeSeriesViewOperand(InputStream inputStream) {
+    try {
+      this.pathString = ReadWriteIOUtils.readString(inputStream);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitTimeSeriesOperand(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.TIMESERIES;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return this.pathString;
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    ReadWriteIOUtils.write(pathString, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    ReadWriteIOUtils.write(pathString, stream);
+  }
+  // endregion
+
+  public String getPathString() {
+    return pathString;
+  }
+
+  public void setPathString(String path) {
+    this.pathString = path;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/TimestampViewOperand.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/TimestampViewOperand.java
new file mode 100644
index 0000000000..b492bad644
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/leaf/TimestampViewOperand.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.metadata.view.viewExpression.leaf;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class TimestampViewOperand extends LeafViewOperand {
+  // region member variables and init functions
+  public TimestampViewOperand() {
+    // do nothing
+  };
+
+  public TimestampViewOperand(ByteBuffer byteBuffer) {
+    // do nothing
+  }
+
+  public TimestampViewOperand(InputStream inputStream) {
+    // do nothing
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitTimeStampOperand(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.TIMESTAMP;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return "TIMESTAMP";
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    // do nothing
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    // do nothing
+  }
+
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/multi/FunctionViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/multi/FunctionViewExpression.java
new file mode 100644
index 0000000000..46c0ea9811
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/multi/FunctionViewExpression.java
@@ -0,0 +1,198 @@
+/*
+ * 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.metadata.view.viewExpression.multi;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+public class FunctionViewExpression extends ViewExpression {
+
+  // region member variables and init functions
+  private final String functionName;
+
+  /**
+   * for a map {key1: value1, key2: value2}, this struct saves String[]{"key1", "value1", "key2",
+   * "value2"}
+   */
+  private final List<String> functionAttributesKeyValueList;
+
+  /**
+   * example: select udf(a, b, udf(c)) from root.sg.d;
+   *
+   * <p>3 expressions [root.sg.d.a, root.sg.d.b, udf(root.sg.d.c)] will be in this field.
+   */
+  private List<ViewExpression> expressions;
+
+  public FunctionViewExpression(String functionName) {
+    this.functionName = functionName;
+    functionAttributesKeyValueList = new ArrayList<>();
+    expressions = new ArrayList<>();
+  }
+
+  public FunctionViewExpression(
+      String functionName,
+      List<String> functionAttributeKeys,
+      List<String> functionAttributeValues,
+      List<ViewExpression> expressions) {
+    this.functionName = functionName;
+    this.functionAttributesKeyValueList = new ArrayList<>();
+    if (functionAttributeKeys.size() == functionAttributeValues.size()) {
+      for (int i = 0; i < functionAttributeKeys.size(); i++) {
+        this.functionAttributesKeyValueList.add(functionAttributeKeys.get(i));
+        this.functionAttributesKeyValueList.add(functionAttributeValues.get(i));
+      }
+    } else {
+      String errorMsg =
+          String.format(
+              "Illegal parameters during FunctionExpression construction. Array length mismatch.");
+      throw new RuntimeException(errorMsg);
+    }
+    this.expressions = expressions;
+  }
+
+  public FunctionViewExpression(ByteBuffer byteBuffer) {
+    functionName = ReadWriteIOUtils.readString(byteBuffer);
+    functionAttributesKeyValueList = ReadWriteIOUtils.readStringList(byteBuffer);
+    int expressionSize = ReadWriteIOUtils.readInt(byteBuffer);
+    expressions = new ArrayList<>();
+    for (int i = 0; i < expressionSize; i++) {
+      expressions.add(ViewExpression.deserialize(byteBuffer));
+    }
+  }
+
+  public FunctionViewExpression(InputStream inputStream) {
+    try {
+      functionName = ReadWriteIOUtils.readString(inputStream);
+      functionAttributesKeyValueList = ReadWriteIOUtils.readStringList(inputStream);
+      int expressionSize = ReadWriteIOUtils.readInt(inputStream);
+      expressions = new ArrayList<>();
+      for (int i = 0; i < expressionSize; i++) {
+        expressions.add(ViewExpression.deserialize(inputStream));
+      }
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitFunctionExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.FUNCTION;
+  }
+
+  @Override
+  protected boolean isLeafOperandInternal() {
+    // if this expression has no children, return true; else return false.
+    if (this.expressions.size() == 0) {
+      return true;
+    }
+    return false;
+  }
+
+  @Override
+  public List<ViewExpression> getChildViewExpressions() {
+    return this.expressions;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    StringBuilder result = new StringBuilder(this.functionName);
+    int keyValueSize = this.functionAttributesKeyValueList.size();
+    if (this.functionAttributesKeyValueList.size() > 1) {
+      result.append("(");
+      for (int i = 0; i + 1 < keyValueSize; i += 2) {
+        result
+            .append(this.functionAttributesKeyValueList.get(i))
+            .append("=")
+            .append(this.functionAttributesKeyValueList.get(i + 1));
+        if (i + 2 >= keyValueSize) {
+          break;
+        }
+        result.append(", ");
+      }
+      result.append(")");
+    }
+    result.append("(");
+    for (int i = 0; i < this.expressions.size(); i++) {
+      result.append(this.expressions.get(i).toString());
+      if (i + 1 >= this.expressions.size()) {
+        break;
+      }
+      result.append(", ");
+    }
+    result.append(")");
+    return result.toString();
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    ReadWriteIOUtils.write(functionName, byteBuffer);
+    ReadWriteIOUtils.writeStringList(functionAttributesKeyValueList, byteBuffer);
+    ReadWriteIOUtils.write(expressions.size(), byteBuffer);
+    for (ViewExpression expression : expressions) {
+      ViewExpression.serialize(expression, byteBuffer);
+    }
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    ReadWriteIOUtils.write(functionName, stream);
+    ReadWriteIOUtils.writeStringList(functionAttributesKeyValueList, stream);
+    ReadWriteIOUtils.write(expressions.size(), stream);
+    for (ViewExpression expression : expressions) {
+      ViewExpression.serialize(expression, stream);
+    }
+  }
+  // endregion
+
+  public String getFunctionName() {
+    return this.functionName;
+  }
+
+  public LinkedHashMap<String, String> getFunctionAttributes() {
+    LinkedHashMap<String, String> result = new LinkedHashMap<>();
+    for (int i = 0; i + 1 < this.functionAttributesKeyValueList.size(); i += 2) {
+      result.put(
+          this.functionAttributesKeyValueList.get(i),
+          this.functionAttributesKeyValueList.get(i + 1));
+    }
+    return result;
+  }
+
+  public List<ViewExpression> getExpressions() {
+    return this.expressions;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ternary/BetweenViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ternary/BetweenViewExpression.java
new file mode 100644
index 0000000000..98bff83c9d
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ternary/BetweenViewExpression.java
@@ -0,0 +1,111 @@
+/*
+ * 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.metadata.view.viewExpression.ternary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class BetweenViewExpression extends TernaryViewExpression {
+
+  // region member variables and init functions
+  /** default value is false. */
+  private final boolean isNotBetween;
+
+  public BetweenViewExpression(
+      ViewExpression firstExpression,
+      ViewExpression secondExpression,
+      ViewExpression thirdExpression,
+      boolean isNotBetween) {
+    super(firstExpression, secondExpression, thirdExpression);
+    this.isNotBetween = isNotBetween;
+  }
+
+  public BetweenViewExpression(
+      ViewExpression firstExpression,
+      ViewExpression secondExpression,
+      ViewExpression thirdExpression) {
+    super(firstExpression, secondExpression, thirdExpression);
+    this.isNotBetween = false;
+  }
+
+  public BetweenViewExpression(ByteBuffer byteBuffer) {
+    super(byteBuffer);
+    this.isNotBetween = ReadWriteIOUtils.readBool(byteBuffer);
+  }
+
+  public BetweenViewExpression(InputStream inputStream) {
+    super(inputStream);
+    try {
+      this.isNotBetween = ReadWriteIOUtils.readBool(inputStream);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitBetweenExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.BETWEEN;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    String basicString =
+        this.firstExpression.toString(true)
+            + " BETWEEN "
+            + this.secondExpression.toString(false)
+            + " AND "
+            + this.secondExpression.toString(false);
+    if (isRoot) {
+      return basicString;
+    }
+    return "(" + basicString + ")";
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    super.serialize(byteBuffer);
+    ReadWriteIOUtils.write(isNotBetween, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    super.serialize(stream);
+    ReadWriteIOUtils.write(isNotBetween, stream);
+  }
+  // endregion
+
+  public boolean isNotBetween() {
+    return isNotBetween;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ternary/TernaryViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ternary/TernaryViewExpression.java
new file mode 100644
index 0000000000..89fd6328e4
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/ternary/TernaryViewExpression.java
@@ -0,0 +1,105 @@
+/*
+ * 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.metadata.view.viewExpression.ternary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class TernaryViewExpression extends ViewExpression {
+
+  // region member variables and init functions
+  protected final ViewExpression firstExpression;
+
+  protected final ViewExpression secondExpression;
+
+  protected final ViewExpression thirdExpression;
+
+  protected TernaryViewExpression(
+      ViewExpression firstExpression,
+      ViewExpression secondExpression,
+      ViewExpression thirdExpression) {
+    this.firstExpression = firstExpression;
+    this.secondExpression = secondExpression;
+    this.thirdExpression = thirdExpression;
+  }
+
+  protected TernaryViewExpression(ByteBuffer byteBuffer) {
+    this.firstExpression = ViewExpression.deserialize(byteBuffer);
+    this.secondExpression = ViewExpression.deserialize(byteBuffer);
+    this.thirdExpression = ViewExpression.deserialize(byteBuffer);
+  }
+
+  protected TernaryViewExpression(InputStream inputStream) {
+    this.firstExpression = ViewExpression.deserialize(inputStream);
+    this.secondExpression = ViewExpression.deserialize(inputStream);
+    this.thirdExpression = ViewExpression.deserialize(inputStream);
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitTernaryExpression(this, context);
+  }
+
+  @Override
+  protected final boolean isLeafOperandInternal() {
+    return false;
+  }
+
+  @Override
+  public final List<ViewExpression> getChildViewExpressions() {
+    return Arrays.asList(firstExpression, secondExpression, thirdExpression);
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    ViewExpression.serialize(firstExpression, byteBuffer);
+    ViewExpression.serialize(secondExpression, byteBuffer);
+    ViewExpression.serialize(thirdExpression, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    ViewExpression.serialize(firstExpression, stream);
+    ViewExpression.serialize(secondExpression, stream);
+    ViewExpression.serialize(thirdExpression, stream);
+  }
+  // endregion
+
+  public ViewExpression getFirstExpression() {
+    return this.firstExpression;
+  }
+
+  public ViewExpression getSecondExpression() {
+    return this.secondExpression;
+  }
+
+  public ViewExpression getThirdExpression() {
+    return this.thirdExpression;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/InViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/InViewExpression.java
new file mode 100644
index 0000000000..b35fed6d16
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/InViewExpression.java
@@ -0,0 +1,106 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+public class InViewExpression extends UnaryViewExpression {
+
+  // region member variables and init functions
+  private final boolean isNotIn;
+
+  private final List<String> valueList;
+
+  public InViewExpression(ViewExpression expression, boolean isNotIn, List<String> values) {
+    super(expression);
+    this.isNotIn = isNotIn;
+    this.valueList = values;
+  }
+
+  public InViewExpression(ByteBuffer byteBuffer) {
+    super(ViewExpression.deserialize(byteBuffer));
+    isNotIn = ReadWriteIOUtils.readBool(byteBuffer);
+    valueList = ReadWriteIOUtils.readStringList(byteBuffer);
+  }
+
+  public InViewExpression(InputStream inputStream) {
+    super(ViewExpression.deserialize(inputStream));
+    try {
+      isNotIn = ReadWriteIOUtils.readBool(inputStream);
+      valueList = ReadWriteIOUtils.readStringList(inputStream);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitInExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.IN;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return "IN " + this.expression.toString();
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    super.serialize(byteBuffer);
+    ReadWriteIOUtils.write(isNotIn, byteBuffer);
+    ReadWriteIOUtils.writeStringList(this.valueList, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    super.serialize(stream);
+    ReadWriteIOUtils.write(isNotIn, stream);
+    ReadWriteIOUtils.writeStringList(this.valueList, stream);
+  }
+  // endregion
+
+  public boolean isNotIn() {
+    return isNotIn;
+  }
+
+  public LinkedHashSet<String> getValuesInLinkedHashSet() {
+    return new LinkedHashSet<>(this.valueList);
+  }
+
+  public List<String> getValueList() {
+    return this.valueList;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/IsNullViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/IsNullViewExpression.java
new file mode 100644
index 0000000000..d2f17c9633
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/IsNullViewExpression.java
@@ -0,0 +1,89 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class IsNullViewExpression extends UnaryViewExpression {
+
+  // region member variables and init functions
+  private final boolean isNot;
+
+  public IsNullViewExpression(ViewExpression expression, boolean isNot) {
+    super(expression);
+    this.isNot = isNot;
+  }
+
+  public IsNullViewExpression(ByteBuffer byteBuffer) {
+    super(ViewExpression.deserialize(byteBuffer));
+    isNot = ReadWriteIOUtils.readBool(byteBuffer);
+  }
+
+  public IsNullViewExpression(InputStream inputStream) {
+    super(ViewExpression.deserialize(inputStream));
+    try {
+      isNot = ReadWriteIOUtils.readBool(inputStream);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitIsNullExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.IS_NULL;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return this.expression.toString(false) + " IS_NULL";
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    super.serialize(byteBuffer);
+    ReadWriteIOUtils.write(isNot, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    super.serialize(stream);
+    ReadWriteIOUtils.write(isNot, stream);
+  }
+  // endregion
+
+  public boolean isNot() {
+    return isNot;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/LikeViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/LikeViewExpression.java
new file mode 100644
index 0000000000..27e1baef19
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/LikeViewExpression.java
@@ -0,0 +1,163 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.regex.Pattern;
+
+public class LikeViewExpression extends UnaryViewExpression {
+
+  // region member variables and init functions
+  private final String patternString;
+  private final Pattern pattern;
+
+  public LikeViewExpression(ViewExpression expression, String patternString) {
+    super(expression);
+    this.patternString = patternString;
+    pattern = this.compile();
+  }
+
+  public LikeViewExpression(ViewExpression expression, String patternString, Pattern pattern) {
+    super(expression);
+    this.patternString = patternString;
+    this.pattern = pattern;
+  }
+
+  public LikeViewExpression(ByteBuffer byteBuffer) {
+    super(ViewExpression.deserialize(byteBuffer));
+    patternString = ReadWriteIOUtils.readString(byteBuffer);
+    pattern = compile();
+  }
+
+  public LikeViewExpression(InputStream inputStream) {
+    super(ViewExpression.deserialize(inputStream));
+    try {
+      patternString = ReadWriteIOUtils.readString(inputStream);
+      pattern = compile();
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLikeExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.LIKE;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    String basicString = this.expression.toString(false) + "LIKE " + this.patternString;
+    if (isRoot) {
+      return basicString;
+    }
+    return "( " + basicString + " )";
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    super.serialize(byteBuffer);
+    ReadWriteIOUtils.write(patternString, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    super.serialize(stream);
+    ReadWriteIOUtils.write(patternString, stream);
+  }
+  // endregion
+
+  public String getPatternString() {
+    return patternString;
+  }
+
+  public Pattern getPattern() {
+    return pattern;
+  }
+
+  /**
+   * This Method is for un-escaping strings except '\' before special string '%', '_', '\', because
+   * we need to use '\' to judge whether to replace this to regexp string
+   */
+  private String unescapeString(String value) {
+    StringBuilder stringBuilder = new StringBuilder();
+    for (int i = 0; i < value.length(); i++) {
+      String ch = String.valueOf(value.charAt(i));
+      if ("\\".equals(ch)) {
+        if (i < value.length() - 1) {
+          String nextChar = String.valueOf(value.charAt(i + 1));
+          if ("%".equals(nextChar) || "_".equals(nextChar) || "\\".equals(nextChar)) {
+            stringBuilder.append(ch);
+          }
+          if ("\\".equals(nextChar)) {
+            i++;
+          }
+        }
+      } else {
+        stringBuilder.append(ch);
+      }
+    }
+    return stringBuilder.toString();
+  }
+
+  /**
+   * The main idea of this part comes from
+   * https://codereview.stackexchange.com/questions/36861/convert-sql-like-to-regex/36864
+   */
+  private Pattern compile() {
+    String unescapeValue = unescapeString(patternString);
+    String specialRegexString = ".^$*+?{}[]|()";
+    StringBuilder patternBuilder = new StringBuilder();
+    patternBuilder.append("^");
+    for (int i = 0; i < unescapeValue.length(); i++) {
+      String ch = String.valueOf(unescapeValue.charAt(i));
+      if (specialRegexString.contains(ch)) {
+        ch = "\\" + unescapeValue.charAt(i);
+      }
+      if (i == 0
+          || !"\\".equals(String.valueOf(unescapeValue.charAt(i - 1)))
+          || i >= 2
+              && "\\\\"
+                  .equals(
+                      patternBuilder.substring(
+                          patternBuilder.length() - 2, patternBuilder.length()))) {
+        patternBuilder.append(ch.replace("%", ".*?").replace("_", "."));
+      } else {
+        patternBuilder.append(ch);
+      }
+    }
+    patternBuilder.append("$");
+    return Pattern.compile(patternBuilder.toString());
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/LogicNotViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/LogicNotViewExpression.java
new file mode 100644
index 0000000000..35ecc779e2
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/LogicNotViewExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class LogicNotViewExpression extends UnaryViewExpression {
+
+  // region member variables and init functions
+  public LogicNotViewExpression(ViewExpression expression) {
+    super(expression);
+  }
+
+  public LogicNotViewExpression(ByteBuffer byteBuffer) {
+    super(ViewExpression.deserialize(byteBuffer));
+  }
+
+  public LogicNotViewExpression(InputStream inputStream) {
+    super(ViewExpression.deserialize(inputStream));
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitLogicNotExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.LOGIC_NOT;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return "NOT " + this.expression.toString(false);
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/NegationViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/NegationViewExpression.java
new file mode 100644
index 0000000000..2e0462c1c5
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/NegationViewExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class NegationViewExpression extends UnaryViewExpression {
+
+  // region member variables and init functions
+  public NegationViewExpression(ViewExpression expression) {
+    super(expression);
+  }
+
+  public NegationViewExpression(ByteBuffer byteBuffer) {
+    super(ViewExpression.deserialize(byteBuffer));
+  }
+
+  public NegationViewExpression(InputStream inputStream) {
+    super(ViewExpression.deserialize(inputStream));
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitNegationExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.NEGATION;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return "NEGATION_OF " + this.expression.toString(false);
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/RegularViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/RegularViewExpression.java
new file mode 100644
index 0000000000..d2aefe48b3
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/RegularViewExpression.java
@@ -0,0 +1,105 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpressionType;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import org.apache.commons.lang3.Validate;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.regex.Pattern;
+
+public class RegularViewExpression extends UnaryViewExpression {
+
+  // region member variables and init functions
+  private final String patternString;
+  private final Pattern pattern;
+
+  public RegularViewExpression(ViewExpression expression, String patternString) {
+    super(expression);
+    this.patternString = patternString;
+    pattern = Pattern.compile(patternString);
+  }
+
+  public RegularViewExpression(ViewExpression expression, String patternString, Pattern pattern) {
+    super(expression);
+    this.patternString = patternString;
+    this.pattern = pattern;
+  }
+
+  public RegularViewExpression(ByteBuffer byteBuffer) {
+    super(ViewExpression.deserialize(byteBuffer));
+    patternString = ReadWriteIOUtils.readString(byteBuffer);
+    pattern = Pattern.compile(Validate.notNull(patternString));
+  }
+
+  public RegularViewExpression(InputStream inputStream) {
+    super(ViewExpression.deserialize(inputStream));
+    try {
+      patternString = ReadWriteIOUtils.readString(inputStream);
+      pattern = Pattern.compile(Validate.notNull(patternString));
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitRegularExpression(this, context);
+  }
+
+  @Override
+  public ViewExpressionType getExpressionType() {
+    return ViewExpressionType.REGEXP;
+  }
+
+  @Override
+  public String toString(boolean isRoot) {
+    return "REGULAR(" + this.expression.toString() + ", " + this.patternString + ")";
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    super.serialize(byteBuffer);
+    ReadWriteIOUtils.write(patternString, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    super.serialize(stream);
+    ReadWriteIOUtils.write(patternString, stream);
+  }
+  // endregion
+  public String getPatternString() {
+    return patternString;
+  }
+
+  public Pattern getPattern() {
+    return pattern;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/UnaryViewExpression.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/UnaryViewExpression.java
new file mode 100644
index 0000000000..3bd78a549e
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/unary/UnaryViewExpression.java
@@ -0,0 +1,73 @@
+/*
+ * 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.metadata.view.viewExpression.unary;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.ViewExpressionVisitor;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class UnaryViewExpression extends ViewExpression {
+
+  // region member variables and init functions
+  protected final ViewExpression expression;
+
+  protected UnaryViewExpression(ViewExpression expression) {
+    this.expression = expression;
+  }
+
+  // endregion
+
+  // region common interfaces that have to be implemented
+  @Override
+  public <R, C> R accept(ViewExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitUnaryExpression(this, context);
+  }
+
+  @Override
+  protected final boolean isLeafOperandInternal() {
+    return false;
+  }
+
+  @Override
+  public final List<ViewExpression> getChildViewExpressions() {
+    // leaf node has no child nodes.
+    return Arrays.asList(expression);
+  }
+
+  @Override
+  protected void serialize(ByteBuffer byteBuffer) {
+    ViewExpression.serialize(expression, byteBuffer);
+  }
+
+  @Override
+  protected void serialize(OutputStream stream) throws IOException {
+    ViewExpression.serialize(expression, stream);
+  }
+  // endregion
+
+  public final ViewExpression getExpression() {
+    return expression;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java
new file mode 100644
index 0000000000..74ac94fb73
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java
@@ -0,0 +1,95 @@
+/*
+ * 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.metadata.view.viewExpression.visitor;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.BinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.multi.FunctionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.TernaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.UnaryViewExpression;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** Use this visitor to find all the paths of time series used in one expression. */
+public class GetSourcePathsVisitor extends ViewExpressionVisitor<List<PartialPath>, Void> {
+
+  @Override
+  public List<PartialPath> visitExpression(ViewExpression expression, Void context) {
+    return new ArrayList<>();
+  }
+
+  @Override
+  public List<PartialPath> visitTimeSeriesOperand(
+      TimeSeriesViewOperand timeSeriesOperand, Void context) {
+    String pathString = timeSeriesOperand.getPathString();
+    try {
+      PartialPath path = new PartialPath(pathString);
+      return Collections.singletonList(path);
+    } catch (IllegalPathException e) {
+      // the path is illegal!
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public List<PartialPath> visitUnaryExpression(
+      UnaryViewExpression unaryViewExpression, Void context) {
+    ViewExpression expression = unaryViewExpression.getExpression();
+    return this.process(expression, null);
+  }
+
+  @Override
+  public List<PartialPath> visitBinaryExpression(
+      BinaryViewExpression binaryViewExpression, Void context) {
+    List<PartialPath> result = new ArrayList<>();
+    List<ViewExpression> expressionList = binaryViewExpression.getChildViewExpressions();
+    for (ViewExpression expression : expressionList) {
+      result.addAll(this.process(expression, null));
+    }
+    return result;
+  }
+
+  @Override
+  public List<PartialPath> visitTernaryExpression(
+      TernaryViewExpression ternaryViewExpression, Void context) {
+    List<PartialPath> result = new ArrayList<>();
+    List<ViewExpression> expressionList = ternaryViewExpression.getChildViewExpressions();
+    for (ViewExpression expression : expressionList) {
+      result.addAll(this.process(expression, null));
+    }
+    return result;
+  }
+
+  @Override
+  public List<PartialPath> visitFunctionExpression(
+      FunctionViewExpression functionViewExpression, Void context) {
+    List<PartialPath> result = new ArrayList<>();
+    List<ViewExpression> expressionList = functionViewExpression.getChildViewExpressions();
+    for (ViewExpression expression : expressionList) {
+      result.addAll(this.process(expression, null));
+    }
+    return result;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/TransformToExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/TransformToExpressionVisitor.java
new file mode 100644
index 0000000000..8a4af23a01
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/TransformToExpressionVisitor.java
@@ -0,0 +1,320 @@
+/*
+ * 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.metadata.view.viewExpression.visitor;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.BinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.AdditionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.ArithmeticBinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.DivisionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.ModuloViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.MultiplicationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.SubtractionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.CompareBinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.EqualToViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.NonEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicAndViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicBinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicOrViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.ConstantViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.LeafViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.NullViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimestampViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.multi.FunctionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.BetweenViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.TernaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.InViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.IsNullViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LikeViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LogicNotViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.NegationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.RegularViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.UnaryViewExpression;
+import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.tsfile.utils.Pair;
+
+import javax.ws.rs.NotSupportedException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TransformToExpressionVisitor extends ViewExpressionVisitor<Expression, Void> {
+
+  @Override
+  public Expression process(ViewExpression viewExpression, Void context) {
+    return viewExpression.accept(this, context);
+  }
+
+  @Override
+  public Expression visitExpression(ViewExpression expression, Void context) {
+    throw new RuntimeException(
+        new NotSupportedException(
+            "visitExpression in TransformToExpressionVisitor is not supported."));
+  }
+
+  // region leaf operand
+  @Override
+  public Expression visitLeafOperand(LeafViewOperand leafViewOperand, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  @Override
+  public Expression visitConstantOperand(ConstantViewOperand constantOperand, Void context) {
+    return new org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand(
+        constantOperand.getDataType(), constantOperand.getValueString());
+  }
+
+  @Override
+  public Expression visitNullOperand(NullViewOperand nullOperand, Void context) {
+    return new org.apache.iotdb.db.mpp.plan.expression.leaf.NullOperand();
+  }
+
+  @Override
+  public Expression visitTimeSeriesOperand(TimeSeriesViewOperand timeSeriesOperand, Void context) {
+    try {
+      PartialPath path = new PartialPath(timeSeriesOperand.getPathString());
+      return new org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand(path);
+    } catch (IllegalPathException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public Expression visitTimeStampOperand(TimestampViewOperand timestampOperand, Void context) {
+    return new org.apache.iotdb.db.mpp.plan.expression.leaf.TimestampOperand();
+  }
+  // endregion
+
+  // region Unary Expressions
+  @Override
+  public Expression visitUnaryExpression(UnaryViewExpression unaryViewExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  @Override
+  public Expression visitInExpression(InViewExpression inExpression, Void context) {
+    Expression child = this.process(inExpression.getExpression(), context);
+    return new org.apache.iotdb.db.mpp.plan.expression.unary.InExpression(
+        child, inExpression.isNotIn(), inExpression.getValuesInLinkedHashSet());
+  }
+
+  @Override
+  public Expression visitIsNullExpression(IsNullViewExpression isNullExpression, Void context) {
+    Expression child = this.process(isNullExpression.getExpression(), context);
+    return new org.apache.iotdb.db.mpp.plan.expression.unary.IsNullExpression(
+        child, isNullExpression.isNot());
+  }
+
+  @Override
+  public Expression visitLikeExpression(LikeViewExpression likeExpression, Void context) {
+    Expression child = this.process(likeExpression.getExpression(), context);
+    return new org.apache.iotdb.db.mpp.plan.expression.unary.LikeExpression(
+        child, likeExpression.getPatternString(), likeExpression.getPattern());
+  }
+
+  @Override
+  public Expression visitLogicNotExpression(
+      LogicNotViewExpression logicNotExpression, Void context) {
+    Expression child = this.process(logicNotExpression.getExpression(), context);
+    return new org.apache.iotdb.db.mpp.plan.expression.unary.LogicNotExpression(child);
+  }
+
+  @Override
+  public Expression visitNegationExpression(
+      NegationViewExpression negationExpression, Void context) {
+    Expression child = this.process(negationExpression.getExpression(), context);
+    return new org.apache.iotdb.db.mpp.plan.expression.unary.NegationExpression(child);
+  }
+
+  @Override
+  public Expression visitRegularExpression(RegularViewExpression regularExpression, Void context) {
+    Expression child = this.process(regularExpression.getExpression(), context);
+    return new org.apache.iotdb.db.mpp.plan.expression.unary.RegularExpression(
+        child, regularExpression.getPatternString(), regularExpression.getPattern());
+  }
+  // endregion
+
+  @Override
+  // region Binary Expressions
+  public Expression visitBinaryExpression(BinaryViewExpression binaryViewExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  private Pair<Expression, Expression> getExpressionsForBinaryExpression(
+      BinaryViewExpression binaryViewExpression) {
+    Expression left = this.process(binaryViewExpression.getLeftExpression(), null);
+    Expression right = this.process(binaryViewExpression.getRightExpression(), null);
+    return new Pair<>(left, right);
+  }
+
+  // region Binary : Arithmetic Binary Expression
+  public Expression visitArithmeticBinaryExpression(
+      ArithmeticBinaryViewExpression arithmeticBinaryExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  public Expression visitAdditionExpression(
+      AdditionViewExpression additionExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(additionExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.AdditionExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitDivisionExpression(
+      DivisionViewExpression divisionExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(divisionExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.DivisionExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitModuloExpression(ModuloViewExpression moduloExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(moduloExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.ModuloExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitMultiplicationExpression(
+      MultiplicationViewExpression multiplicationExpression, Void context) {
+    Pair<Expression, Expression> pair =
+        this.getExpressionsForBinaryExpression(multiplicationExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.MultiplicationExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitSubtractionExpression(
+      SubtractionViewExpression subtractionExpression, Void context) {
+    Pair<Expression, Expression> pair =
+        this.getExpressionsForBinaryExpression(subtractionExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.SubtractionExpression(
+        pair.left, pair.right);
+  }
+  // endregion
+
+  // region Binary: Compare Binary Expression
+  public Expression visitCompareBinaryExpression(
+      CompareBinaryViewExpression compareBinaryExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  public Expression visitEqualToExpression(EqualToViewExpression equalToExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(equalToExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.EqualToExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitGreaterEqualExpression(
+      GreaterEqualViewExpression greaterEqualExpression, Void context) {
+    Pair<Expression, Expression> pair =
+        this.getExpressionsForBinaryExpression(greaterEqualExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.GreaterEqualExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitGreaterThanExpression(
+      GreaterThanViewExpression greaterThanExpression, Void context) {
+    Pair<Expression, Expression> pair =
+        this.getExpressionsForBinaryExpression(greaterThanExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.GreaterThanExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitLessEqualExpression(
+      LessEqualViewExpression lessEqualExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(lessEqualExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.LessEqualExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitLessThanExpression(
+      LessThanViewExpression lessThanExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(lessThanExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.LessThanExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitNonEqualExpression(
+      NonEqualViewExpression nonEqualExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(nonEqualExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.NonEqualExpression(
+        pair.left, pair.right);
+  }
+  // endregion
+
+  // region Binary : Logic Binary Expression
+  public Expression visitLogicBinaryExpression(
+      LogicBinaryViewExpression logicBinaryExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  public Expression visitLogicAndExpression(
+      LogicAndViewExpression logicAndExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(logicAndExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.LogicAndExpression(
+        pair.left, pair.right);
+  }
+
+  public Expression visitLogicOrExpression(LogicOrViewExpression logicOrExpression, Void context) {
+    Pair<Expression, Expression> pair = this.getExpressionsForBinaryExpression(logicOrExpression);
+    return new org.apache.iotdb.db.mpp.plan.expression.binary.LogicOrExpression(
+        pair.left, pair.right);
+  }
+  // endregion
+
+  // endregion
+
+  // region Ternary Expressions
+  public Expression visitTernaryExpression(
+      TernaryViewExpression ternaryViewExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  public Expression visitBetweenExpression(
+      BetweenViewExpression betweenViewExpression, Void context) {
+    Expression first = this.process(betweenViewExpression.getFirstExpression(), null);
+    Expression second = this.process(betweenViewExpression.getSecondExpression(), null);
+    Expression third = this.process(betweenViewExpression.getThirdExpression(), null);
+    return new org.apache.iotdb.db.mpp.plan.expression.ternary.BetweenExpression(
+        first, second, third, betweenViewExpression.isNotBetween());
+  }
+  // endregion
+
+  // region FunctionExpression
+  public Expression visitFunctionExpression(
+      FunctionViewExpression functionViewExpression, Void context) {
+    List<ViewExpression> viewExpressionList = functionViewExpression.getExpressions();
+    List<Expression> expressionList = new ArrayList<>();
+    for (ViewExpression viewExpression : viewExpressionList) {
+      expressionList.add(this.process(viewExpression, null));
+    }
+    return new org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression(
+        functionViewExpression.getFunctionName(),
+        functionViewExpression.getFunctionAttributes(),
+        expressionList);
+  }
+  // endregion
+
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/ViewExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/ViewExpressionVisitor.java
new file mode 100644
index 0000000000..a2023bc898
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/ViewExpressionVisitor.java
@@ -0,0 +1,219 @@
+/*
+ * 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.metadata.view.viewExpression.visitor;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.BinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.AdditionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.ArithmeticBinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.DivisionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.ModuloViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.MultiplicationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.SubtractionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.CompareBinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.EqualToViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.NonEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicAndViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicBinaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicOrViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.ConstantViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.LeafViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.NullViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimestampViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.multi.FunctionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.BetweenViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.TernaryViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.InViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.IsNullViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LikeViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LogicNotViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.NegationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.RegularViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.UnaryViewExpression;
+
+/**
+ * This class provides a visitor of {@link ViewExpression}, which can be extended to create a
+ * visitor which only needs to handle a subset of the available methods.
+ *
+ * @param <R> The return type of the visit operation.
+ * @param <C> The context information during visiting.
+ */
+public abstract class ViewExpressionVisitor<R, C> {
+
+  public R process(ViewExpression expression, C context) {
+    return expression.accept(this, context);
+  }
+
+  public abstract R visitExpression(ViewExpression expression, C context);
+
+  // region leaf operand
+  public R visitLeafOperand(LeafViewOperand leafViewOperand, C context) {
+    return visitExpression(leafViewOperand, context);
+  }
+
+  public R visitConstantOperand(ConstantViewOperand constantOperand, C context) {
+    return visitLeafOperand(constantOperand, context);
+  }
+
+  public R visitNullOperand(NullViewOperand nullOperand, C context) {
+    return visitLeafOperand(nullOperand, context);
+  }
+
+  public R visitTimeSeriesOperand(TimeSeriesViewOperand timeSeriesOperand, C context) {
+    return visitLeafOperand(timeSeriesOperand, context);
+  }
+
+  public R visitTimeStampOperand(TimestampViewOperand timestampOperand, C context) {
+    return visitLeafOperand(timestampOperand, context);
+  }
+  // endregion
+
+  // region Unary Expressions
+  public R visitUnaryExpression(UnaryViewExpression unaryViewExpression, C context) {
+    return visitExpression(unaryViewExpression, context);
+  }
+
+  public R visitInExpression(InViewExpression inExpression, C context) {
+    return visitUnaryExpression(inExpression, context);
+  }
+
+  public R visitIsNullExpression(IsNullViewExpression isNullExpression, C context) {
+    return visitUnaryExpression(isNullExpression, context);
+  }
+
+  public R visitLikeExpression(LikeViewExpression likeExpression, C context) {
+    return visitUnaryExpression(likeExpression, context);
+  }
+
+  public R visitLogicNotExpression(LogicNotViewExpression logicNotExpression, C context) {
+    return visitUnaryExpression(logicNotExpression, context);
+  }
+
+  public R visitNegationExpression(NegationViewExpression negationExpression, C context) {
+    return visitUnaryExpression(negationExpression, context);
+  }
+
+  public R visitRegularExpression(RegularViewExpression regularExpression, C context) {
+    return visitUnaryExpression(regularExpression, context);
+  }
+  // endregion
+
+  // region Binary Expressions
+  public R visitBinaryExpression(BinaryViewExpression binaryViewExpression, C context) {
+    return visitExpression(binaryViewExpression, context);
+  }
+
+  // region Binary : Arithmetic Binary Expression
+  public R visitArithmeticBinaryExpression(
+      ArithmeticBinaryViewExpression arithmeticBinaryExpression, C context) {
+    return visitBinaryExpression(arithmeticBinaryExpression, context);
+  }
+
+  public R visitAdditionExpression(AdditionViewExpression additionExpression, C context) {
+    return visitArithmeticBinaryExpression(additionExpression, context);
+  }
+
+  public R visitDivisionExpression(DivisionViewExpression divisionExpression, C context) {
+    return visitArithmeticBinaryExpression(divisionExpression, context);
+  }
+
+  public R visitModuloExpression(ModuloViewExpression moduloExpression, C context) {
+    return visitArithmeticBinaryExpression(moduloExpression, context);
+  }
+
+  public R visitMultiplicationExpression(
+      MultiplicationViewExpression multiplicationExpression, C context) {
+    return visitArithmeticBinaryExpression(multiplicationExpression, context);
+  }
+
+  public R visitSubtractionExpression(SubtractionViewExpression subtractionExpression, C context) {
+    return visitArithmeticBinaryExpression(subtractionExpression, context);
+  }
+  // endregion
+
+  // region Binary: Compare Binary Expression
+  public R visitCompareBinaryExpression(
+      CompareBinaryViewExpression compareBinaryExpression, C context) {
+    return visitBinaryExpression(compareBinaryExpression, context);
+  }
+
+  public R visitEqualToExpression(EqualToViewExpression equalToExpression, C context) {
+    return visitCompareBinaryExpression(equalToExpression, context);
+  }
+
+  public R visitGreaterEqualExpression(
+      GreaterEqualViewExpression greaterEqualExpression, C context) {
+    return visitCompareBinaryExpression(greaterEqualExpression, context);
+  }
+
+  public R visitGreaterThanExpression(GreaterThanViewExpression greaterThanExpression, C context) {
+    return visitCompareBinaryExpression(greaterThanExpression, context);
+  }
+
+  public R visitLessEqualExpression(LessEqualViewExpression lessEqualExpression, C context) {
+    return visitCompareBinaryExpression(lessEqualExpression, context);
+  }
+
+  public R visitLessThanExpression(LessThanViewExpression lessThanExpression, C context) {
+    return visitCompareBinaryExpression(lessThanExpression, context);
+  }
+
+  public R visitNonEqualExpression(NonEqualViewExpression nonEqualExpression, C context) {
+    return visitCompareBinaryExpression(nonEqualExpression, context);
+  }
+  // endregion
+
+  // region Binary : Logic Binary Expression
+  public R visitLogicBinaryExpression(LogicBinaryViewExpression logicBinaryExpression, C context) {
+    return visitBinaryExpression(logicBinaryExpression, context);
+  }
+
+  public R visitLogicAndExpression(LogicAndViewExpression logicAndExpression, C context) {
+    return visitLogicBinaryExpression(logicAndExpression, context);
+  }
+
+  public R visitLogicOrExpression(LogicOrViewExpression logicOrExpression, C context) {
+    return visitLogicBinaryExpression(logicOrExpression, context);
+  }
+  // endregion
+
+  // endregion
+
+  // region Ternary Expressions
+  public R visitTernaryExpression(TernaryViewExpression ternaryViewExpression, C context) {
+    return visitExpression(ternaryViewExpression, context);
+  }
+
+  public R visitBetweenExpression(BetweenViewExpression betweenViewExpression, C context) {
+    return visitTernaryExpression(betweenViewExpression, context);
+  }
+  // endregion
+
+  // region FunctionExpression
+  public R visitFunctionExpression(FunctionViewExpression functionViewExpression, C context) {
+    return visitExpression(functionViewExpression, context);
+  }
+  // endregion
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/visitor/SchemaExecutionVisitor.java b/server/src/main/java/org/apache/iotdb/db/metadata/visitor/SchemaExecutionVisitor.java
index d2ca0038b2..853b3fe5c4 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/visitor/SchemaExecutionVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/visitor/SchemaExecutionVisitor.java
@@ -26,12 +26,14 @@ import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.exception.metadata.MeasurementAlreadyExistException;
 import org.apache.iotdb.db.exception.metadata.template.TemplateIsInUseException;
+import org.apache.iotdb.db.metadata.plan.schemaregion.impl.write.CreateLogicalViewPlanImpl;
 import org.apache.iotdb.db.metadata.plan.schemaregion.impl.write.SchemaRegionWritePlanFactory;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateAlignedTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateTimeSeriesPlan;
 import org.apache.iotdb.db.metadata.schemaregion.ISchemaRegion;
 import org.apache.iotdb.db.metadata.template.ClusterTemplateManager;
 import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.ActivateTemplateNode;
@@ -39,6 +41,7 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.AlterTimeSe
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.BatchActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.ConstructSchemaBlackListNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateLogicalViewNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.DeactivateTemplateNode;
@@ -440,6 +443,25 @@ public class SchemaExecutionVisitor extends PlanVisitor<TSStatus, ISchemaRegion>
     }
   }
 
+  @Override
+  public TSStatus visitCreateLogicalView(CreateLogicalViewNode node, ISchemaRegion schemaRegion) {
+    Map<PartialPath, ViewExpression> viewPathToSourceMap = node.getViewPathToSourceExpressionMap();
+    List<TSStatus> failingStatus = new ArrayList<>();
+    for (Map.Entry<PartialPath, ViewExpression> entry : viewPathToSourceMap.entrySet()) {
+      try {
+        schemaRegion.createLogicalView(
+            new CreateLogicalViewPlanImpl(entry.getKey(), entry.getValue()));
+      } catch (MetadataException e) {
+        logger.error("{}: MetaData error: ", IoTDBConstant.GLOBAL_DB_NAME, e);
+        failingStatus.add(RpcUtils.getStatus(e.getErrorCode(), e.getMessage()));
+      }
+    }
+    if (!failingStatus.isEmpty()) {
+      return RpcUtils.getStatus(failingStatus);
+    }
+    return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS, "Execute successfully");
+  }
+
   @Override
   public TSStatus visitPlan(PlanNode node, ISchemaRegion context) {
     return null;
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
index 824fa23ce0..1270955119 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
@@ -182,6 +182,9 @@ public class ColumnHeaderConstant {
   public static final String HYPERPARAMETER = "Hyperparameter";
   public static final String MODEL_PATH = "ModelPath";
 
+  // column names for views (eg. logical view)
+  public static final String VIEW_TYPE = "ViewType";
+
   public static final List<ColumnHeader> lastQueryColumnHeaders =
       ImmutableList.of(
           new ColumnHeader(TIMESERIES, TSDataType.TEXT),
@@ -199,7 +202,8 @@ public class ColumnHeaderConstant {
           new ColumnHeader(TAGS, TSDataType.TEXT),
           new ColumnHeader(ATTRIBUTES, TSDataType.TEXT),
           new ColumnHeader(DEADBAND, TSDataType.TEXT),
-          new ColumnHeader(DEADBAND_PARAMETERS, TSDataType.TEXT));
+          new ColumnHeader(DEADBAND_PARAMETERS, TSDataType.TEXT),
+          new ColumnHeader(VIEW_TYPE, TSDataType.TEXT));
 
   public static final List<ColumnHeader> showDevicesWithSgColumnHeaders =
       ImmutableList.of(
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/executor/RegionWriteExecutor.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/executor/RegionWriteExecutor.java
index c035edabe5..a5bbf26195 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/executor/RegionWriteExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/executor/RegionWriteExecutor.java
@@ -47,6 +47,7 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.ActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.BatchActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateLogicalViewNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.InternalBatchActivateTemplateNode;
@@ -685,6 +686,54 @@ public class RegionWriteExecutor {
         context.getRegionWriteValidationRWLock().readLock().unlock();
       }
     }
+
+    @Override
+    public RegionExecutionResult visitCreateLogicalView(
+        CreateLogicalViewNode node, WritePlanNodeExecutionContext context) {
+      ISchemaRegion schemaRegion =
+          SchemaEngine.getInstance().getSchemaRegion((SchemaRegionId) context.getRegionId());
+      if (config.getSchemaRegionConsensusProtocolClass().equals(ConsensusFactory.RATIS_CONSENSUS)) {
+        context.getRegionWriteValidationRWLock().writeLock().lock();
+        try {
+          // step 1. make sure all target paths are NOT exist.
+          List<PartialPath> targetPaths = node.getViewPathList();
+          List<MetadataException> failingMetadataException = new ArrayList<>();
+          for (PartialPath thisPath : targetPaths) {
+            // no alias list for a view, so the third parameter is null
+            Map<Integer, MetadataException> failingMeasurementMap =
+                schemaRegion.checkMeasurementExistence(
+                    thisPath.getDevicePath(),
+                    Collections.singletonList(thisPath.getMeasurement()),
+                    null);
+            // merge all exception into one map
+            for (Map.Entry<Integer, MetadataException> entry : failingMeasurementMap.entrySet()) {
+              failingMetadataException.add(entry.getValue());
+            }
+          }
+          // if there is some exception, handle each exception and return first of them.
+          if (!failingMetadataException.isEmpty()) {
+            MetadataException metadataException = failingMetadataException.get(0);
+            LOGGER.error("Metadata error: ", metadataException);
+            RegionExecutionResult result = new RegionExecutionResult();
+            result.setAccepted(false);
+            result.setMessage(metadataException.getMessage());
+            result.setStatus(
+                RpcUtils.getStatus(
+                    metadataException.getErrorCode(), metadataException.getMessage()));
+            return result;
+          }
+          // step 2. make sure all source paths are existed.
+          // TODO: CRTODO use a more efficient method
+          //                List<PartialPath> sourcePaths = node.getAllTimeSeriesPathInSource();
+          return super.visitCreateLogicalView(node, context);
+        } finally {
+          context.getRegionWriteValidationRWLock().writeLock().unlock();
+        }
+      } else {
+        return super.visitCreateLogicalView(node, context);
+      }
+      // end of visitCreateLogicalView
+    }
   }
 
   private static class WritePlanNodeExecutionContext {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/TimeSeriesSchemaSource.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/TimeSeriesSchemaSource.java
index 9e52ece3ec..575fb4c7bb 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/TimeSeriesSchemaSource.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/TimeSeriesSchemaSource.java
@@ -98,9 +98,17 @@ public class TimeSeriesSchemaSource implements ISchemaSource<ITimeSeriesSchemaIn
     builder.writeNullableText(0, series.getFullPath());
     builder.writeNullableText(1, series.getAlias());
     builder.writeNullableText(2, database);
-    builder.writeNullableText(3, series.getSchema().getType().toString());
-    builder.writeNullableText(4, series.getSchema().getEncodingType().toString());
-    builder.writeNullableText(5, series.getSchema().getCompressor().toString());
+    if (series.isLogicalView()) {
+      builder.writeNullableText(3, "");
+      builder.writeNullableText(4, "null");
+      builder.writeNullableText(5, "null");
+      builder.writeNullableText(10, "logical");
+    } else {
+      builder.writeNullableText(3, series.getSchema().getType().toString());
+      builder.writeNullableText(4, series.getSchema().getEncodingType().toString());
+      builder.writeNullableText(5, series.getSchema().getCompressor().toString());
+      builder.writeNullableText(10, "");
+    }
     builder.writeNullableText(6, mapToString(series.getTags()));
     builder.writeNullableText(7, mapToString(series.getAttributes()));
     builder.writeNullableText(8, deadbandInfo.left);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index 248a7209fa..c9980705f9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -111,6 +111,7 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesState
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.DatabaseSchemaStatement;
@@ -3019,4 +3020,48 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
 
     analysis.setWhereExpression(whereExpression);
   }
+
+  // create Logical View
+  @Override
+  public Analysis visitCreateLogicalView(
+      CreateLogicalViewStatement createLogicalViewStatement, MPPQueryContext context) {
+    Analysis analysis = new Analysis();
+    // TODO: CRTODO: add more analyzing
+    context.setQueryType(QueryType.WRITE);
+
+    // check target paths; check source expressions.
+    Pair<Boolean, Exception> checkResult = createLogicalViewStatement.checkAll();
+    if (checkResult.left == false) {
+      throw new RuntimeException(checkResult.right);
+    }
+
+    Analysis queryAnalysis = null;
+    if (createLogicalViewStatement.getQueryStatement() != null) {
+      // analysis query statement
+      //      AnalyzeVisitor queryVisitor = new AnalyzeVisitor(this.partitionFetcher,
+      // this.schemaFetcher);
+      //      queryAnalysis =
+      // queryVisitor.visitQuery(createLogicalViewStatement.getQueryStatement(), null);
+      this.visitQuery(createLogicalViewStatement.getQueryStatement(), null);
+      // get all expression from resultColumns
+      List<ResultColumn> resultColumns =
+          createLogicalViewStatement.getQueryStatement().getSelectComponent().getResultColumns();
+      List<Expression> expressionList = new ArrayList<>();
+      for (ResultColumn resultCol : resultColumns) {
+        expressionList.add(resultCol.getExpression());
+      }
+      createLogicalViewStatement.setSourceExpressions(expressionList);
+    }
+    analysis.setStatement(createLogicalViewStatement);
+
+    // set schema partition info, this info will be used to split logical plan node.
+    PathPatternTree patternTree = new PathPatternTree();
+    for (PartialPath thisFullPath : createLogicalViewStatement.getTargetPathList()) {
+      patternTree.appendFullPath(thisFullPath);
+    }
+    SchemaPartition schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(patternTree);
+    analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+
+    return analysis;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/TransformToViewExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/TransformToViewExpressionVisitor.java
new file mode 100644
index 0000000000..b19e9a460d
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/TransformToViewExpressionVisitor.java
@@ -0,0 +1,391 @@
+/*
+ * 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.visitor;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.AdditionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.DivisionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.ModuloViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.MultiplicationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.SubtractionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.EqualToViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.GreaterThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.LessThanViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.compare.NonEqualViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicAndViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.logic.LogicOrViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.ConstantViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.NullViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimestampViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.multi.FunctionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.BetweenViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.InViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.IsNullViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LikeViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.LogicNotViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.NegationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.unary.RegularViewExpression;
+import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.AdditionExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.ArithmeticBinaryExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.BinaryExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.CompareBinaryExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.DivisionExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.EqualToExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterEqualExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterThanExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.LessEqualExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.LessThanExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.LogicAndExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.LogicBinaryExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.LogicOrExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.ModuloExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.MultiplicationExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.NonEqualExpression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.SubtractionExpression;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.LeafOperand;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.NullOperand;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.TimestampOperand;
+import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
+import org.apache.iotdb.db.mpp.plan.expression.ternary.BetweenExpression;
+import org.apache.iotdb.db.mpp.plan.expression.ternary.TernaryExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.InExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.IsNullExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.LikeExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.LogicNotExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.NegationExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.RegularExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression;
+import org.apache.iotdb.tsfile.utils.Pair;
+
+import javax.ws.rs.NotSupportedException;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TransformToViewExpressionVisitor extends ExpressionVisitor<ViewExpression, Void> {
+
+  @Override
+  public ViewExpression process(Expression expression, Void context) {
+    return expression.accept(this, context);
+  }
+
+  @Override
+  public ViewExpression visitExpression(Expression expression, Void context) {
+    throw new RuntimeException(
+        new NotSupportedException(
+            "visitExpression in TransformToViewExpressionVisitor is not supported."));
+  }
+
+  // region leaf operand
+  @Override
+  public ViewExpression visitLeafOperand(LeafOperand leafOperand, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  @Override
+  public ViewExpression visitConstantOperand(ConstantOperand constantOperand, Void context) {
+    return new ConstantViewOperand(constantOperand.getDataType(), constantOperand.getValueString());
+  }
+
+  @Override
+  public ViewExpression visitNullOperand(NullOperand nullOperand, Void context) {
+    return new NullViewOperand();
+  }
+
+  @Override
+  public ViewExpression visitTimeSeriesOperand(TimeSeriesOperand timeSeriesOperand, Void context) {
+    return new TimeSeriesViewOperand(timeSeriesOperand.getPath().toString());
+  }
+
+  @Override
+  public ViewExpression visitTimeStampOperand(TimestampOperand timestampOperand, Void context) {
+    return new TimestampViewOperand();
+  }
+  // endregion
+
+  // region Unary Expressions
+  @Override
+  public ViewExpression visitUnaryExpression(UnaryExpression unaryExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  @Override
+  public ViewExpression visitInExpression(InExpression inExpression, Void context) {
+    ViewExpression child = this.process(inExpression.getExpression(), context);
+    List<String> valueList = new ArrayList<>(inExpression.getValues());
+    return new InViewExpression(child, inExpression.isNotIn(), valueList);
+  }
+
+  @Override
+  public ViewExpression visitIsNullExpression(IsNullExpression isNullExpression, Void context) {
+    ViewExpression child = this.process(isNullExpression.getExpression(), context);
+    return new IsNullViewExpression(child, isNullExpression.isNot());
+  }
+
+  @Override
+  public ViewExpression visitLikeExpression(LikeExpression likeExpression, Void context) {
+    ViewExpression child = this.process(likeExpression.getExpression(), context);
+    return new LikeViewExpression(
+        child, likeExpression.getPatternString(), likeExpression.getPattern());
+  }
+
+  @Override
+  public ViewExpression visitLogicNotExpression(
+      LogicNotExpression logicNotExpression, Void context) {
+    ViewExpression child = this.process(logicNotExpression.getExpression(), context);
+    return new LogicNotViewExpression(child);
+  }
+
+  @Override
+  public ViewExpression visitNegationExpression(
+      NegationExpression negationExpression, Void context) {
+    ViewExpression child = this.process(negationExpression.getExpression(), context);
+    return new NegationViewExpression(child);
+  }
+
+  @Override
+  public ViewExpression visitRegularExpression(RegularExpression regularExpression, Void context) {
+    ViewExpression child = this.process(regularExpression.getExpression(), context);
+    return new RegularViewExpression(
+        child, regularExpression.getPatternString(), regularExpression.getPattern());
+  }
+  // endregion
+
+  // region Binary Expressions
+  @Override
+  public ViewExpression visitBinaryExpression(BinaryExpression binaryExpression, Void context) {
+    if (binaryExpression instanceof ArithmeticBinaryExpression) {
+      return this.visitArithmeticBinaryExpression(
+          (ArithmeticBinaryExpression) binaryExpression, context);
+    } else if (binaryExpression instanceof CompareBinaryExpression) {
+      return this.visitCompareBinaryExpression((CompareBinaryExpression) binaryExpression, context);
+    } else if (binaryExpression instanceof LogicBinaryExpression) {
+      return this.visitLogicBinaryExpression((LogicBinaryExpression) binaryExpression, context);
+    }
+    throw new RuntimeException(
+        new NotSupportedException(
+            "unsupported expression type:" + binaryExpression.getExpressionType()));
+  }
+
+  private Pair<ViewExpression, ViewExpression> getExpressionsForBinaryExpression(
+      BinaryExpression binaryExpression) {
+    ViewExpression left = this.process(binaryExpression.getLeftExpression(), null);
+    ViewExpression right = this.process(binaryExpression.getRightExpression(), null);
+    return new Pair<>(left, right);
+  }
+
+  // region Binary : Arithmetic Binary Expression
+  @Override
+  public ViewExpression visitArithmeticBinaryExpression(
+      ArithmeticBinaryExpression arithmeticBinaryExpression, Void context) {
+    if (arithmeticBinaryExpression instanceof AdditionExpression) {
+      return this.visitAdditionExpression((AdditionExpression) arithmeticBinaryExpression, context);
+    } else if (arithmeticBinaryExpression instanceof DivisionExpression) {
+      return this.visitDivisionExpression((DivisionExpression) arithmeticBinaryExpression, context);
+    } else if (arithmeticBinaryExpression instanceof ModuloExpression) {
+      return this.visitModuloExpression((ModuloExpression) arithmeticBinaryExpression, context);
+    } else if (arithmeticBinaryExpression instanceof MultiplicationExpression) {
+      return this.visitMultiplicationExpression(
+          (MultiplicationExpression) arithmeticBinaryExpression, context);
+    } else if (arithmeticBinaryExpression instanceof SubtractionExpression) {
+      return this.visitSubtractionExpression(
+          (SubtractionExpression) arithmeticBinaryExpression, context);
+    }
+    throw new RuntimeException(
+        new NotSupportedException(
+            "unsupported expression type:" + arithmeticBinaryExpression.getExpressionType()));
+  }
+
+  public ViewExpression visitAdditionExpression(
+      AdditionExpression additionExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(additionExpression);
+    return new AdditionViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitDivisionExpression(
+      DivisionExpression divisionExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(divisionExpression);
+    return new DivisionViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitModuloExpression(ModuloExpression moduloExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(moduloExpression);
+    return new ModuloViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitMultiplicationExpression(
+      MultiplicationExpression multiplicationExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(multiplicationExpression);
+    return new MultiplicationViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitSubtractionExpression(
+      SubtractionExpression subtractionExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(subtractionExpression);
+    return new SubtractionViewExpression(pair.left, pair.right);
+  }
+  // endregion
+
+  // region Binary: Compare Binary Expression
+  @Override
+  public ViewExpression visitCompareBinaryExpression(
+      CompareBinaryExpression compareBinaryExpression, Void context) {
+    if (compareBinaryExpression instanceof EqualToExpression) {
+      return this.visitEqualToExpression((EqualToExpression) compareBinaryExpression, context);
+    } else if (compareBinaryExpression instanceof GreaterEqualExpression) {
+      return this.visitGreaterEqualExpression(
+          (GreaterEqualExpression) compareBinaryExpression, context);
+    } else if (compareBinaryExpression instanceof GreaterThanExpression) {
+      return this.visitGreaterThanExpression(
+          (GreaterThanExpression) compareBinaryExpression, context);
+    } else if (compareBinaryExpression instanceof LessEqualExpression) {
+      return this.visitLessEqualExpression((LessEqualExpression) compareBinaryExpression, context);
+    } else if (compareBinaryExpression instanceof LessThanExpression) {
+      return this.visitLessThanExpression((LessThanExpression) compareBinaryExpression, context);
+    } else if (compareBinaryExpression instanceof NonEqualExpression) {
+      return this.visitNonEqualExpression((NonEqualExpression) compareBinaryExpression, context);
+    }
+    throw new RuntimeException(
+        new NotSupportedException(
+            "unsupported expression type:" + compareBinaryExpression.getExpressionType()));
+  }
+
+  public ViewExpression visitEqualToExpression(EqualToExpression equalToExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(equalToExpression);
+    return new EqualToViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitGreaterEqualExpression(
+      GreaterEqualExpression greaterEqualExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(greaterEqualExpression);
+    return new GreaterEqualViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitGreaterThanExpression(
+      GreaterThanExpression greaterThanExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(greaterThanExpression);
+    return new GreaterThanViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitLessEqualExpression(
+      LessEqualExpression lessEqualExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(lessEqualExpression);
+    return new LessEqualViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitLessThanExpression(
+      LessThanExpression lessThanExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(lessThanExpression);
+    return new LessThanViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitNonEqualExpression(
+      NonEqualExpression nonEqualExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(nonEqualExpression);
+    return new NonEqualViewExpression(pair.left, pair.right);
+  }
+  // endregion
+
+  // region Binary : Logic Binary Expression
+  @Override
+  public ViewExpression visitLogicBinaryExpression(
+      LogicBinaryExpression logicBinaryExpression, Void context) {
+    if (logicBinaryExpression instanceof LogicAndExpression) {
+      return this.visitLogicAndExpression((LogicAndExpression) logicBinaryExpression, context);
+    } else if (logicBinaryExpression instanceof LogicOrExpression) {
+      return this.visitLogicOrExpression((LogicOrExpression) logicBinaryExpression, context);
+    }
+    throw new RuntimeException(
+        new NotSupportedException(
+            "unsupported expression type:" + logicBinaryExpression.getExpressionType()));
+  }
+
+  public ViewExpression visitLogicAndExpression(
+      LogicAndExpression logicAndExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(logicAndExpression);
+    return new LogicAndViewExpression(pair.left, pair.right);
+  }
+
+  public ViewExpression visitLogicOrExpression(LogicOrExpression logicOrExpression, Void context) {
+    Pair<ViewExpression, ViewExpression> pair =
+        this.getExpressionsForBinaryExpression(logicOrExpression);
+    return new LogicOrViewExpression(pair.left, pair.right);
+  }
+  // endregion
+
+  // endregion
+
+  // region Ternary Expressions
+  @Override
+  public ViewExpression visitTernaryExpression(TernaryExpression ternaryExpression, Void context) {
+    throw new RuntimeException(new NotSupportedException("Can not construct abstract class."));
+  }
+
+  @Override
+  public ViewExpression visitBetweenExpression(BetweenExpression betweenExpression, Void context) {
+    ViewExpression first = this.process(betweenExpression.getFirstExpression(), null);
+    ViewExpression second = this.process(betweenExpression.getSecondExpression(), null);
+    ViewExpression third = this.process(betweenExpression.getSecondExpression(), null);
+    return new BetweenViewExpression(first, second, third, betweenExpression.isNotBetween());
+  }
+  // endregion
+
+  // region FunctionExpression
+  @Override
+  public ViewExpression visitFunctionExpression(
+      FunctionExpression functionExpression, Void context) {
+    List<Expression> expressionList = functionExpression.getExpressions();
+    List<ViewExpression> viewExpressionList = new ArrayList<>();
+    for (Expression expression : expressionList) {
+      viewExpressionList.add(this.process(expression, null));
+    }
+    LinkedHashMap<String, String> map = functionExpression.getFunctionAttributes();
+    List<String> keyList = new ArrayList<>();
+    List<String> valueList = new ArrayList<>();
+    for (Map.Entry<String, String> entry : map.entrySet()) {
+      keyList.add(entry.getKey());
+      valueList.add(entry.getValue());
+    }
+    return new FunctionViewExpression(
+        functionExpression.getFunctionName(), keyList, valueList, viewExpressionList);
+  }
+  // endregion
+
+}
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 28203751ee..bea8913d26 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
@@ -113,6 +113,7 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSlotListStatemen
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateContinuousQueryStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateFunctionStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreatePipePluginStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTriggerStatement;
@@ -960,6 +961,91 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
     return new ShowContinuousQueriesStatement();
   }
 
+  // Create Logical View
+  @Override
+  public Statement visitCreateLogicalView(IoTDBSqlParser.CreateLogicalViewContext ctx) {
+    CreateLogicalViewStatement createLogicalViewStatement = new CreateLogicalViewStatement();
+    // parse target
+    parseViewTargetPaths(ctx.viewTargetPaths(), createLogicalViewStatement);
+    // parse source
+    parseViewSourcePaths(ctx.viewSourcePaths(), createLogicalViewStatement);
+
+    return createLogicalViewStatement;
+  }
+
+  // parse suffix paths in logical view
+  private PartialPath parseViewSuffixPath(IoTDBSqlParser.ViewSuffixPathsContext ctx) {
+    List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
+        ctx.nodeNameWithoutWildcard();
+    String[] nodeList = new String[nodeNamesWithoutStar.size()];
+    for (int i = 0; i < nodeNamesWithoutStar.size(); i++) {
+      nodeList[i] = parseNodeNameWithoutWildCard(nodeNamesWithoutStar.get(i));
+    }
+    return new PartialPath(nodeList);
+  }
+
+  // parse target paths in CreateLogicalView statement
+  private void parseViewTargetPaths(
+      IoTDBSqlParser.ViewTargetPathsContext ctx,
+      CreateLogicalViewStatement createLogicalViewStatement) {
+    // full paths
+    if (ctx.fullPath() != null && ctx.fullPath().size() > 0) {
+      List<IoTDBSqlParser.FullPathContext> fullPathContextList = ctx.fullPath();
+      List<PartialPath> pathList = new ArrayList<>();
+      for (IoTDBSqlParser.FullPathContext pathContext : fullPathContextList) {
+        pathList.add(parseFullPath(pathContext));
+      }
+      createLogicalViewStatement.setTargetFullPaths(pathList);
+    }
+    // prefix path and suffix paths
+    if (ctx.prefixPath() != null
+        && ctx.viewSuffixPaths() != null
+        && ctx.viewSuffixPaths().size() > 0) {
+      IoTDBSqlParser.PrefixPathContext prefixPathContext = ctx.prefixPath();
+      PartialPath prefixPath = parsePrefixPath(prefixPathContext);
+      List<IoTDBSqlParser.ViewSuffixPathsContext> suffixPathContextList = ctx.viewSuffixPaths();
+      List<PartialPath> suffixPathList = new ArrayList<>();
+      for (IoTDBSqlParser.ViewSuffixPathsContext suffixPathContext : suffixPathContextList) {
+        suffixPathList.add(parseViewSuffixPath(suffixPathContext));
+      }
+      createLogicalViewStatement.setTargetPathsGroup(prefixPath, suffixPathList);
+    }
+  }
+
+  // parse source paths in CreateLogicalView statement
+  private void parseViewSourcePaths(
+      IoTDBSqlParser.ViewSourcePathsContext ctx,
+      CreateLogicalViewStatement createLogicalViewStatement) {
+    // full paths
+    if (ctx.fullPath() != null && ctx.fullPath().size() > 0) {
+      List<IoTDBSqlParser.FullPathContext> fullPathContextList = ctx.fullPath();
+      List<PartialPath> pathList = new ArrayList<>();
+      for (IoTDBSqlParser.FullPathContext pathContext : fullPathContextList) {
+        pathList.add(parseFullPath(pathContext));
+      }
+      createLogicalViewStatement.setSourceFullPaths(pathList);
+    }
+    // prefix path and suffix paths
+    if (ctx.prefixPath() != null
+        && ctx.viewSuffixPaths() != null
+        && ctx.viewSuffixPaths().size() > 0) {
+      IoTDBSqlParser.PrefixPathContext prefixPathContext = ctx.prefixPath();
+      PartialPath prefixPath = parsePrefixPath(prefixPathContext);
+      List<IoTDBSqlParser.ViewSuffixPathsContext> suffixPathContextList = ctx.viewSuffixPaths();
+      List<PartialPath> suffixPathList = new ArrayList<>();
+      for (IoTDBSqlParser.ViewSuffixPathsContext suffixPathContext : suffixPathContextList) {
+        suffixPathList.add(parseViewSuffixPath(suffixPathContext));
+      }
+      createLogicalViewStatement.setSourcePathsGroup(prefixPath, suffixPathList);
+    }
+    if (ctx.selectClause() != null && ctx.fromClause() != null) {
+      QueryStatement queryStatement = new QueryStatement();
+      queryStatement.setSelectComponent(parseSelectClause(ctx.selectClause(), queryStatement));
+      queryStatement.setFromComponent(parseFromClause(ctx.fromClause()));
+      createLogicalViewStatement.setSourceQueryStatement(queryStatement);
+    }
+  }
+
   // Create Model =====================================================================
   @Override
   public Statement visitCreateModel(IoTDBSqlParser.CreateModelContext ctx) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
index a8cb30fac9..6c12ab2f00 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
@@ -21,17 +21,20 @@ package org.apache.iotdb.db.mpp.plan.planner;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction;
 import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
 import org.apache.iotdb.db.mpp.common.MPPQueryContext;
 import org.apache.iotdb.db.mpp.plan.analyze.Analysis;
 import org.apache.iotdb.db.mpp.plan.analyze.ExpressionAnalyzer;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
+import org.apache.iotdb.db.mpp.plan.expression.visitor.TransformToViewExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.load.LoadTsFileNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.ActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.AlterTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.BatchActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateLogicalViewNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.InternalBatchActivateTemplateNode;
@@ -67,6 +70,7 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesState
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildNodesStatement;
@@ -812,4 +816,21 @@ public class LogicalPlanVisitor extends StatementVisitor<PlanNode, MPPQueryConte
             .planLimit(showQueriesStatement.getRowLimit());
     return planBuilder.getRoot();
   }
+
+  @Override
+  public PlanNode visitCreateLogicalView(
+      CreateLogicalViewStatement createLogicalViewStatement, MPPQueryContext context) {
+    // Transform all Expressions into ViewExpressions.
+    TransformToViewExpressionVisitor transformToViewExpressionVisitor =
+        new TransformToViewExpressionVisitor();
+    List<ViewExpression> viewExpressionList = new ArrayList<>();
+    List<Expression> expressionList = createLogicalViewStatement.getSourceExpressionList();
+    for (Expression expression : expressionList) {
+      viewExpressionList.add(transformToViewExpressionVisitor.process(expression, null));
+    }
+    return new CreateLogicalViewNode(
+        context.getQueryId().genPlanNodeId(),
+        createLogicalViewStatement.getTargetPathList(),
+        viewExpressionList);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
index 11b7b71717..762238ac91 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
@@ -39,6 +39,7 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.AlterTimeSe
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.BatchActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.ConstructSchemaBlackListNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateLogicalViewNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.DeactivateTemplateNode;
@@ -167,7 +168,8 @@ public enum PlanNodeType {
   INTERNAL_CREATE_MULTI_TIMESERIES((short) 69),
   IDENTITY_SINK((short) 70),
   SHUFFLE_SINK((short) 71),
-  BATCH_ACTIVATE_TEMPLATE((short) 72);
+  BATCH_ACTIVATE_TEMPLATE((short) 72),
+  CREATE_LOGICAL_VIEW((short) 73);
 
   public static final int BYTES = Short.BYTES;
 
@@ -360,6 +362,8 @@ public enum PlanNodeType {
         return ShuffleSinkNode.deserialize(buffer);
       case 72:
         return BatchActivateTemplateNode.deserialize(buffer);
+      case 73:
+        return CreateLogicalViewNode.deserialize(buffer);
       default:
         throw new IllegalArgumentException("Invalid node type: " + nodeType);
     }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanVisitor.java
index 86ef541965..771a805014 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanVisitor.java
@@ -38,6 +38,7 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.AlterTimeSe
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.BatchActivateTemplateNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.ConstructSchemaBlackListNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateLogicalViewNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.DeactivateTemplateNode;
@@ -401,4 +402,8 @@ public abstract class PlanVisitor<R, C> {
   public R visitDeleteData(DeleteDataNode node, C context) {
     return visitPlan(node, context);
   }
+
+  public R visitCreateLogicalView(CreateLogicalViewNode node, C context) {
+    return visitPlan(node, context);
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/metedata/write/CreateLogicalViewNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/metedata/write/CreateLogicalViewNode.java
new file mode 100644
index 0000000000..52e2a03519
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/metedata/write/CreateLogicalViewNode.java
@@ -0,0 +1,250 @@
+/*
+ * 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.planner.plan.node.metedata.write;
+
+import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathDeserializeUtil;
+import org.apache.iotdb.db.metadata.plan.schemaregion.write.ICreateLogicalViewPlan;
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.visitor.GetSourcePathsVisitor;
+import org.apache.iotdb.db.mpp.plan.analyze.Analysis;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNodeId;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNodeType;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanVisitor;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.WritePlanNode;
+import org.apache.iotdb.tsfile.exception.NotImplementedException;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class CreateLogicalViewNode extends WritePlanNode implements ICreateLogicalViewPlan {
+
+  /**
+   * A map from target path to source expression. Yht target path is the name of this logical view,
+   * and the source expression is the data source of this view.
+   */
+  private Map<PartialPath, ViewExpression> viewPathToSourceMap;
+
+  /**
+   * This variable will be set in function splitByPartition() according to analysis. And it will be
+   * set when creating new split nodes.
+   */
+  private TRegionReplicaSet regionReplicaSet = null;
+
+  public CreateLogicalViewNode(
+      PlanNodeId id, List<PartialPath> paths, List<ViewExpression> expressions) {
+    super(id);
+    this.viewPathToSourceMap = convertTargetAndSourceListsToMap(paths, expressions);
+  }
+
+  public CreateLogicalViewNode(
+      PlanNodeId id, Map<PartialPath, ViewExpression> viewPathToSourceMap) {
+    super(id);
+    this.viewPathToSourceMap = viewPathToSourceMap;
+  }
+
+  public CreateLogicalViewNode(
+      PlanNodeId id,
+      Map<PartialPath, ViewExpression> viewPathToSourceMap,
+      TRegionReplicaSet regionReplicaSet) {
+    super(id);
+    this.viewPathToSourceMap = viewPathToSourceMap;
+    this.regionReplicaSet = regionReplicaSet;
+  }
+
+  protected final Map<PartialPath, ViewExpression> convertTargetAndSourceListsToMap(
+      List<PartialPath> paths, List<ViewExpression> expressions) {
+    if (paths.size() != expressions.size()) {
+      return null;
+    }
+    Map<PartialPath, ViewExpression> result = new HashMap<>();
+    for (int i = 0; i < paths.size(); i++) {
+      result.put(paths.get(i), expressions.get(i));
+    }
+    return result;
+  }
+
+  // region Interfaces in ICreateLogicalViewPlan
+  @Override
+  public int getViewSize() {
+    return this.viewPathToSourceMap.size();
+  }
+
+  @Override
+  public Map<PartialPath, ViewExpression> getViewPathToSourceExpressionMap() {
+    return this.viewPathToSourceMap;
+  }
+
+  @Override
+  public List<PartialPath> getViewPathList() {
+    List<PartialPath> result = new ArrayList<>(this.viewPathToSourceMap.keySet());
+    return result;
+  }
+
+  @Override
+  public void setViewPathToSourceExpressionMap(
+      Map<PartialPath, ViewExpression> viewPathToSourceExpressionMap) {
+    this.viewPathToSourceMap = viewPathToSourceExpressionMap;
+  }
+
+  @Override
+  public <R, C> R accept(PlanVisitor<R, C> visitor, C schemaRegion) {
+    return visitor.visitCreateLogicalView(this, schemaRegion);
+  }
+  // endregion
+
+  // region Interfaces in WritePlanNode or PlanNode
+
+  @Override
+  public TRegionReplicaSet getRegionReplicaSet() {
+    return this.regionReplicaSet;
+  }
+
+  @Override
+  public List<PlanNode> getChildren() {
+    return new ArrayList<>();
+  }
+
+  @Override
+  public void addChild(PlanNode child) {
+    // do nothing. this node should never have any child
+  }
+
+  @Override
+  public PlanNode clone() {
+    // TODO: CRTODO, complete this method
+    throw new NotImplementedException("Clone of CreateMultiTimeSeriesNode is not implemented");
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null || getClass() != obj.getClass()) {
+      return false;
+    }
+    CreateLogicalViewNode that = (CreateLogicalViewNode) obj;
+    return (this.getPlanNodeId().equals(that.getPlanNodeId())
+        && Objects.equals(this.viewPathToSourceMap, that.viewPathToSourceMap));
+  }
+
+  @Override
+  public int allowedChildCount() {
+    // this node should never have any child
+    return NO_CHILD_ALLOWED;
+  }
+
+  @Override
+  public List<String> getOutputColumnNames() {
+    // TODO: CRTODO, complete this method
+    throw new NotImplementedException(
+        "getOutputColumnNames of CreateMultiTimeSeriesNode is not implemented");
+  }
+
+  @Override
+  protected void serializeAttributes(ByteBuffer byteBuffer) {
+    PlanNodeType.CREATE_LOGICAL_VIEW.serialize(byteBuffer);
+    // serialize other member variables for this node
+    ReadWriteIOUtils.write(this.viewPathToSourceMap.size(), byteBuffer);
+    for (Map.Entry<PartialPath, ViewExpression> entry : viewPathToSourceMap.entrySet()) {
+      entry.getKey().serialize(byteBuffer);
+      ViewExpression.serialize(entry.getValue(), byteBuffer);
+    }
+  }
+
+  @Override
+  protected void serializeAttributes(DataOutputStream stream) throws IOException {
+    PlanNodeType.CREATE_LOGICAL_VIEW.serialize(stream);
+    // serialize other member variables for this node
+    ReadWriteIOUtils.write(this.viewPathToSourceMap.size(), stream);
+    for (Map.Entry<PartialPath, ViewExpression> entry : viewPathToSourceMap.entrySet()) {
+      entry.getKey().serialize(stream);
+      ViewExpression.serialize(entry.getValue(), stream);
+    }
+  }
+
+  public static CreateLogicalViewNode deserialize(ByteBuffer byteBuffer) {
+    // deserialize member variables
+    Map<PartialPath, ViewExpression> viewPathToSourceMap = new HashMap<>();
+    int size = byteBuffer.getInt();
+    PartialPath path;
+    ViewExpression viewExpression;
+    for (int i = 0; i < size; i++) {
+      path = (PartialPath) PathDeserializeUtil.deserialize(byteBuffer);
+      viewExpression = ViewExpression.deserialize(byteBuffer);
+      viewPathToSourceMap.put(path, viewExpression);
+    }
+    // deserialize PlanNodeId next
+    PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer);
+    return new CreateLogicalViewNode(planNodeId, viewPathToSourceMap);
+  }
+
+  @Override
+  public List<WritePlanNode> splitByPartition(Analysis analysis) {
+    Map<TRegionReplicaSet, Map<PartialPath, ViewExpression>> splitMap = new HashMap<>();
+    for (Map.Entry<PartialPath, ViewExpression> entry : this.viewPathToSourceMap.entrySet()) {
+      // for each entry in the map for target path to source expression,
+      // build a map from TRegionReplicaSet to this entry.
+      // Please note that getSchemaRegionReplicaSet needs a device path as parameter.
+      TRegionReplicaSet regionReplicaSet =
+          analysis.getSchemaPartitionInfo().getSchemaRegionReplicaSet(entry.getKey().getDevice());
+
+      // create a map if the key(regionReplicaSet) is not exists,
+      // then put this entry into this map(from regionReplicaSet to this entry)
+      splitMap
+          .computeIfAbsent(regionReplicaSet, k -> new HashMap<>())
+          .put(entry.getKey(), entry.getValue());
+    }
+
+    // split this node into several nodes according to their regionReplicaSet
+    List<WritePlanNode> result = new ArrayList<>();
+    for (Map.Entry<TRegionReplicaSet, Map<PartialPath, ViewExpression>> entry :
+        splitMap.entrySet()) {
+      // for each entry in splitMap, create a plan node.
+      result.add(new CreateLogicalViewNode(getPlanNodeId(), entry.getValue(), entry.getKey()));
+    }
+    return result;
+  }
+  // endregion
+
+  public List<PartialPath> getAllTimeSeriesPathInSource() {
+    List<ViewExpression> sourceExpressions = new ArrayList<>();
+    for (Map.Entry<PartialPath, ViewExpression> entry : this.viewPathToSourceMap.entrySet()) {
+      sourceExpressions.add(entry.getValue());
+    }
+    // for each view expression, get the partial path for time series operand
+    List<PartialPath> result = new ArrayList<>();
+    GetSourcePathsVisitor getSourcePathsVisitor = new GetSourcePathsVisitor();
+    for (ViewExpression expression : sourceExpressions) {
+      result.addAll(getSourcePathsVisitor.process(expression, null));
+    }
+    return result;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementType.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementType.java
index 4bf8190495..e3ebe07d41 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementType.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementType.java
@@ -167,4 +167,6 @@ public enum StatementType {
   SHOW_SPACE_QUOTA,
   SET_THROTTLE_QUOTA,
   SHOW_THROTTLE_QUOTA,
+
+  CREATE_LOGICAL_VIEW,
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
index 8a5bcf18ab..5f716f95b5 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
@@ -42,6 +42,7 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSlotListStatemen
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateContinuousQueryStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateFunctionStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreatePipePluginStatement;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
@@ -240,6 +241,12 @@ public abstract class StatementVisitor<R, C> {
     return visitStatement(showPipePluginsStatement, context);
   }
 
+  // Create Logical View
+  public R visitCreateLogicalView(
+      CreateLogicalViewStatement createLogicalViewStatement, C context) {
+    return visitStatement(createLogicalViewStatement, context);
+  }
+
   // ML Model
   public R visitCreateModel(CreateModelStatement createModelStatement, C context) {
     return visitStatement(createModelStatement, context);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/CreateLogicalViewStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/CreateLogicalViewStatement.java
new file mode 100644
index 0000000000..b96aa42dd7
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/CreateLogicalViewStatement.java
@@ -0,0 +1,246 @@
+/*
+ * 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.statement.metadata;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
+import org.apache.iotdb.db.mpp.plan.statement.Statement;
+import org.apache.iotdb.db.mpp.plan.statement.StatementType;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
+import org.apache.iotdb.tsfile.utils.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** CREATE LOGICAL VIEW statement. */
+public class CreateLogicalViewStatement extends Statement {
+
+  // the paths of this view
+  private viewPaths targetPaths;
+
+  // the paths of sources
+  private viewPaths sourcePaths;
+  private QueryStatement queryStatement;
+
+  public CreateLogicalViewStatement() {
+    super();
+    this.statementType = StatementType.CREATE_LOGICAL_VIEW;
+    this.sourcePaths = new viewPaths();
+    this.targetPaths = new viewPaths();
+  }
+
+  // region Interfaces about setting and getting
+
+  // get paths
+  @Override
+  public List<PartialPath> getPaths() {
+    return this.getTargetPathList();
+  }
+
+  public List<PartialPath> getTargetPathList() {
+    return this.targetPaths.fullPathList;
+  }
+
+  public List<Expression> getSourceExpressionList() {
+    this.sourcePaths.generateExpressionsIfNecessary();
+    return this.sourcePaths.expressionsList;
+  }
+
+  public QueryStatement getQueryStatement() {
+    return this.queryStatement;
+  }
+
+  // set source paths
+  public void setSourceFullPaths(List<PartialPath> paths) {
+    this.sourcePaths.setViewPathType(ViewPathType.FULL_PATH_LIST);
+    this.sourcePaths.setFullPathList(paths);
+  }
+
+  public void setSourcePathsGroup(PartialPath prefixPath, List<PartialPath> suffixPaths) {
+    this.sourcePaths.setViewPathType(ViewPathType.PATHS_GROUP);
+    this.sourcePaths.setPrefixOfPathsGroup(prefixPath);
+    this.sourcePaths.setSuffixOfPathsGroup(suffixPaths);
+    this.sourcePaths.generateFullPathsFromPathsGroup();
+  }
+
+  public void setSourceQueryStatement(QueryStatement queryStatement) {
+    this.sourcePaths.setViewPathType(ViewPathType.QUERY_STATEMENT);
+    this.queryStatement = queryStatement;
+  }
+
+  /**
+   * This function must be called after analyzing query statement. Expressions that analyzed should
+   * be set through here.
+   *
+   * @param expressionList
+   */
+  public void setSourceExpressions(List<Expression> expressionList) {
+    this.sourcePaths.setExpressionsList(expressionList);
+  }
+
+  // set target paths
+  public void setTargetFullPaths(List<PartialPath> paths) {
+    this.targetPaths.setViewPathType(ViewPathType.FULL_PATH_LIST);
+    this.targetPaths.setFullPathList(paths);
+  }
+
+  public void setTargetPathsGroup(PartialPath prefixPath, List<PartialPath> suffixPaths) {
+    this.targetPaths.setViewPathType(ViewPathType.PATHS_GROUP);
+    this.targetPaths.setPrefixOfPathsGroup(prefixPath);
+    this.targetPaths.setSuffixOfPathsGroup(suffixPaths);
+    this.targetPaths.generateFullPathsFromPathsGroup();
+  }
+
+  // endregion
+
+  // region Interfaces for checking
+  /**
+   * Check errors in targetPaths.
+   *
+   * @return Pair<Boolean, Exception>. True: checks passed, exception is null; False: checks failed,
+   *     returns exception.
+   */
+  public Pair<Boolean, Exception> checkTargetPaths() {
+    for (PartialPath thisPath : this.getTargetPathList()) {
+      if (thisPath.getNodeLength() < 3) {
+        return new Pair<>(false, new IllegalPathException(thisPath.getFullPath()));
+      }
+    }
+    return new Pair<>(true, null);
+  }
+
+  /**
+   * Check errors in sourcePaths. Only usable when not using query statement. If this statement is
+   * generated with a query statement, check always pass; if not, check each full paths.
+   *
+   * @return Pair<Boolean, Exception>. True: checks passed, exception is null; False: checks failed,
+   *     returns exception.
+   */
+  public Pair<Boolean, Exception> checkSourcePathsIfNotUsingQueryStatement() {
+    if (this.sourcePaths.viewPathType == ViewPathType.PATHS_GROUP
+        || this.sourcePaths.viewPathType == ViewPathType.FULL_PATH_LIST) {
+      for (PartialPath thisPath : this.sourcePaths.fullPathList) {
+        if (thisPath.getNodeLength() < 3) {
+          return new Pair<>(false, new IllegalPathException(thisPath.getFullPath()));
+        }
+      }
+    }
+    return new Pair<>(true, null);
+  }
+
+  public Pair<Boolean, Exception> checkAll() {
+    Pair<Boolean, Exception> result = null;
+    result = this.checkTargetPaths();
+    if (result.left == false) return result;
+    result = this.checkSourcePathsIfNotUsingQueryStatement();
+    if (result.left == false) return result;
+    return new Pair<>(true, null);
+  }
+
+  // endregion
+
+  @Override
+  public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
+    return visitor.visitCreateLogicalView(this, context);
+  }
+
+  // region private classes
+
+  private enum ViewPathType {
+    FULL_PATH_LIST,
+    PATHS_GROUP,
+    QUERY_STATEMENT
+  }
+
+  /**
+   * A private class to save all paths' info in targetPaths and sourcePaths except query statement.
+   *
+   * <p>fullPathList: CREATE VIEW root.db.device.temp AS root.ln.d.s01 PathGroup: CREATE VIEW
+   * root.db(device.temp, status) AS root.ln(d.s01, wf.abc.s02)
+   */
+  private class viewPaths {
+    public ViewPathType viewPathType = ViewPathType.FULL_PATH_LIST;
+    public List<PartialPath> fullPathList = null;
+    public PartialPath prefixOfPathsGroup = null;
+    public List<PartialPath> suffixOfPathsGroup = null;
+
+    public List<Expression> expressionsList = null;
+
+    public void addPath(PartialPath path) {
+      if (this.fullPathList == null) {
+        this.fullPathList = new ArrayList<>();
+        this.fullPathList.add(path);
+      } else {
+        this.fullPathList.add(path);
+      }
+    }
+
+    public void setFullPathList(List<PartialPath> pathList) {
+      this.fullPathList = pathList;
+    }
+
+    public void setPrefixOfPathsGroup(PartialPath path) {
+      this.prefixOfPathsGroup = path;
+    }
+
+    public void setSuffixOfPathsGroup(List<PartialPath> pathList) {
+      this.suffixOfPathsGroup = pathList;
+    }
+
+    public void setViewPathType(ViewPathType viewPathType) {
+      this.viewPathType = viewPathType;
+    }
+
+    public void generateFullPathsFromPathsGroup() {
+      if (prefixOfPathsGroup != null && suffixOfPathsGroup != null) {
+        this.fullPathList = new ArrayList<>();
+        for (PartialPath suffixPath : suffixOfPathsGroup) {
+          PartialPath pathToAdd = prefixOfPathsGroup.concatPath(suffixPath);
+          this.addPath(pathToAdd);
+        }
+      }
+    }
+
+    public void generateExpressionsIfNecessary() {
+      if (this.viewPathType == ViewPathType.FULL_PATH_LIST
+          || this.viewPathType == ViewPathType.PATHS_GROUP) {
+        if (this.fullPathList != null) {
+          this.expressionsList = new ArrayList<>();
+          for (PartialPath path : this.fullPathList) {
+            TimeSeriesOperand tsExpression = new TimeSeriesOperand(path);
+            this.expressionsList.add(tsExpression);
+          }
+        }
+      } else if (this.viewPathType == ViewPathType.QUERY_STATEMENT) {
+        // no nothing. expressions should be set by setExpressionsList
+      }
+    }
+
+    public void setExpressionsList(List<Expression> expressionsList) {
+      this.expressionsList = expressionsList;
+    }
+    // end of viewPaths
+  }
+
+  // endregion
+}
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/view/ViewExpressionToStringTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/view/ViewExpressionToStringTest.java
new file mode 100644
index 0000000000..aad623eb10
--- /dev/null
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/view/ViewExpressionToStringTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.metadata.view;
+
+import org.apache.iotdb.db.metadata.view.viewExpression.ViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.AdditionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.binary.arithmetic.MultiplicationViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.ConstantViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimeSeriesViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.leaf.TimestampViewOperand;
+import org.apache.iotdb.db.metadata.view.viewExpression.multi.FunctionViewExpression;
+import org.apache.iotdb.db.metadata.view.viewExpression.ternary.BetweenViewExpression;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class ViewExpressionToStringTest {
+
+  @Test
+  public void testTimseriesOperand() {
+    String fullPath = new String("root.db.device.s01");
+    TimeSeriesViewOperand timeSeriesViewOperand = new TimeSeriesViewOperand(fullPath);
+    Assert.assertEquals(fullPath, timeSeriesViewOperand.toString());
+    Assert.assertEquals(fullPath, timeSeriesViewOperand.toString(true));
+    Assert.assertEquals(fullPath, timeSeriesViewOperand.toString(false));
+  }
+
+  @Test
+  public void testAdditionViewExpression() {
+    TimeSeriesViewOperand timeSeriesViewOperand = new TimeSeriesViewOperand("root.db.device.s01");
+    ConstantViewOperand constantViewOperand = new ConstantViewOperand(TSDataType.INT32, "2");
+    AdditionViewExpression add =
+        new AdditionViewExpression(timeSeriesViewOperand, constantViewOperand);
+
+    String expectedRoot = new String("root.db.device.s01 + 2");
+    String expectedNotRoot = new String("(root.db.device.s01 + 2)");
+    Assert.assertEquals(expectedRoot, add.toString());
+    Assert.assertEquals(expectedRoot, add.toString(true));
+    Assert.assertEquals(expectedNotRoot, add.toString(false));
+  }
+
+  @Test
+  public void testTwoBinaryExpression() {
+    TimeSeriesViewOperand ts1 = new TimeSeriesViewOperand("root.db.device.s01");
+    ConstantViewOperand constant2 = new ConstantViewOperand(TSDataType.INT32, "2");
+    AdditionViewExpression add = new AdditionViewExpression(ts1, constant2);
+    TimeSeriesViewOperand ts2 = new TimeSeriesViewOperand("root.ln.d.s01");
+    MultiplicationViewExpression multiplication = new MultiplicationViewExpression(add, ts2);
+
+    String expectedRoot = new String("(root.db.device.s01 + 2) * root.ln.d.s01");
+    String expectedNotRoot = new String("((root.db.device.s01 + 2) * root.ln.d.s01)");
+    Assert.assertEquals(expectedRoot, multiplication.toString());
+    Assert.assertEquals(expectedRoot, multiplication.toString(true));
+    Assert.assertEquals(expectedNotRoot, multiplication.toString(false));
+  }
+
+  @Test
+  public void testFunctionViewExpression01() {
+    String functionName = "func";
+    FunctionViewExpression func = new FunctionViewExpression(functionName);
+
+    String expectedRoot = new String("func()");
+    String expectedNotRoot = new String("func()");
+    Assert.assertEquals(expectedRoot, func.toString());
+    Assert.assertEquals(expectedRoot, func.toString(true));
+    Assert.assertEquals(expectedNotRoot, func.toString(false));
+  }
+
+  @Test
+  public void testFunctionViewExpression02() {
+    String functionName = "MAX";
+    List<String> keys = new ArrayList<>();
+    List<String> values = new ArrayList<>();
+
+    TimeSeriesViewOperand ts1 = new TimeSeriesViewOperand("root.db.device.s01");
+    ConstantViewOperand constant2 = new ConstantViewOperand(TSDataType.INT32, "2");
+    AdditionViewExpression add = new AdditionViewExpression(ts1, constant2);
+    TimeSeriesViewOperand ts2 = new TimeSeriesViewOperand("root.ln.d.s01");
+    List<ViewExpression> exps = Arrays.asList(add, ts2);
+
+    FunctionViewExpression func = new FunctionViewExpression(functionName, keys, values, exps);
+
+    String expectedRoot = new String("MAX(root.db.device.s01 + 2, root.ln.d.s01)");
+    String expectedNotRoot = new String("MAX(root.db.device.s01 + 2, root.ln.d.s01)");
+    Assert.assertEquals(expectedRoot, func.toString());
+    Assert.assertEquals(expectedRoot, func.toString(true));
+    Assert.assertEquals(expectedNotRoot, func.toString(false));
+  }
+
+  @Test
+  public void testFunctionViewExpression03() {
+    String functionName = "CAST";
+    List<String> keys = Collections.singletonList("type");
+    List<String> values = Collections.singletonList("INT32");
+
+    TimeSeriesViewOperand ts2 = new TimeSeriesViewOperand("root.ln.d.s01");
+    List<ViewExpression> exps = Collections.singletonList(ts2);
+
+    FunctionViewExpression func = new FunctionViewExpression(functionName, keys, values, exps);
+
+    String expectedRoot = new String("CAST(type=INT32)(root.ln.d.s01)");
+    String expectedNotRoot = new String("CAST(type=INT32)(root.ln.d.s01)");
+    Assert.assertEquals(expectedRoot, func.toString());
+    Assert.assertEquals(expectedRoot, func.toString(true));
+    Assert.assertEquals(expectedNotRoot, func.toString(false));
+  }
+
+  @Test
+  public void testFunctionViewExpression04() {
+    String functionName = "CAST";
+    List<String> keys = Collections.singletonList("type");
+    List<String> values = Collections.singletonList("INT32");
+
+    TimeSeriesViewOperand ts2 = new TimeSeriesViewOperand("root.ln.d.s01");
+    List<ViewExpression> exps = Collections.singletonList(ts2);
+
+    FunctionViewExpression func = new FunctionViewExpression(functionName, keys, values, exps);
+
+    String expectedRoot = new String("CAST(type=INT32)(root.ln.d.s01)");
+    String expectedNotRoot = new String("CAST(type=INT32)(root.ln.d.s01)");
+    Assert.assertEquals(expectedRoot, func.toString());
+    Assert.assertEquals(expectedRoot, func.toString(true));
+    Assert.assertEquals(expectedNotRoot, func.toString(false));
+  }
+
+  @Test
+  public void testFunctionViewExpression05() {
+    String functionName = "FUNC";
+    List<String> keys = Arrays.asList("type", "key");
+    List<String> values = Arrays.asList("INT32", "value");
+
+    TimeSeriesViewOperand ts1 = new TimeSeriesViewOperand("root.db.device.s01");
+    TimeSeriesViewOperand ts2 = new TimeSeriesViewOperand("root.ln.d.s01");
+    List<ViewExpression> exps = Arrays.asList(ts1, ts2);
+
+    FunctionViewExpression func = new FunctionViewExpression(functionName, keys, values, exps);
+
+    String expectedRoot =
+        new String("FUNC(type=INT32, key=value)(root.db.device.s01, root.ln.d.s01)");
+    String expectedNotRoot =
+        new String("FUNC(type=INT32, key=value)(root.db.device.s01, root.ln.d.s01)");
+    Assert.assertEquals(expectedRoot, func.toString());
+    Assert.assertEquals(expectedRoot, func.toString(true));
+    Assert.assertEquals(expectedNotRoot, func.toString(false));
+  }
+
+  @Test
+  public void testBetweenViewExpression() {
+    TimestampViewOperand timestamp01 = new TimestampViewOperand();
+    TimestampViewOperand timestamp02 = new TimestampViewOperand();
+    TimeSeriesViewOperand ts1 = new TimeSeriesViewOperand("root.db.device.s01");
+    BetweenViewExpression exp = new BetweenViewExpression(ts1, timestamp01, timestamp02);
+
+    String expectedRoot = new String("root.db.device.s01 BETWEEN TIMESTAMP AND TIMESTAMP");
+    String expectedNotRoot = new String("(root.db.device.s01 BETWEEN TIMESTAMP AND TIMESTAMP)");
+    Assert.assertEquals(expectedRoot, exp.toString());
+    Assert.assertEquals(expectedRoot, exp.toString(true));
+    Assert.assertEquals(expectedNotRoot, exp.toString(false));
+  }
+}