@Test
  public void innerJoinOnMultiColumns() {
    expectedHeader = new String[] {"time", "device1", "value1", "device2", "value2"};
    sql =
        "SELECT "
            + "  t1.time, "
            + "  t1.device as device1, "
            + "  t1.value as value1, "
            + "  t2.device as device2, "
            + "  t2.value as value2 "
            + "FROM "
            + "  tableA t1, tableB t2 "
            + "where t1.time = t2.time and t1.device = t2.device order by t1.time";
    retArray =
        new String[] {
          "2020-01-01T00:00:03.000Z,d1,3,d1,30,", "2020-01-01T00:00:05.000Z,d2,5,d2,50,",
        };
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    sql =
        "SELECT "
            + "  t1.time, "
            + "  t1.device as device1, "
            + "  t1.value as value1, "
            + "  t2.device as device2, "
            + "  t2.value as value2 "
            + "FROM "
            + "  tableA t1 cross join tableB t2 "
            + "where t1.time = t2.time and t1.device = t2.device order by t1.time";
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    sql =
        "SELECT "
            + "  t1.time, "
            + "  t1.device as device1, "
            + "  t1.value as value1, "
            + "  t2.device as device2, "
            + "  t2.value as value2 "
            + "FROM "
            + "  tableA t1 JOIN tableB t2 "
            + "ON t1.time = t2.time and t1.device = t2.device order by t1.time";
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    expectedHeader = new String[] {"time", "device", "value1", "value2"};
    sql =
        "SELECT "
            + "  time, device, "
            + "  t1.value as value1, "
            + "  t2.value as value2 "
            + "FROM "
            + "  tableA t1 JOIN tableB t2 "
            + "USING(time, device) ORDER BY time";
    retArray =
        new String[] {
          "2020-01-01T00:00:03.000Z,d1,3,30,", "2020-01-01T00:00:05.000Z,d2,5,50,",
        };
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    expectedHeader = new String[] {"device", "device", "num", "num", "floatnum", "floatnum"};
    sql =
        "select t0.device, t1.device, t0.num, t1.num, t0.floatnum, t1.floatnum from table0 t0 join table1 t1 on t0.device=t1.device AND t0.attr2=t1.attr2 AND t0.num>t1.num AND t0.floatnum>t1.floatnum ORDER BY t0.device,t1.device,t0.num,t1.num";
    retArray =
        new String[] {
          "d1,d1,4,1,213.1,12.123,", "d1,d1,6,3,1231.21,231.2121,", "d1,d1,14,1,231.34,12.123,",
        };
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    expectedHeader = new String[] {"time1", "time2", "device1", "device2"};
    sql =
        "select t1.time as time1, t2.time as time2, t1.device as device1, t2.device as device2 from tablea t1 join tableb t2 "
            + "on cast(substring(t1.device,2) as int32) = cast(substring(t2.device,2) as int32)+1 order by time1,time2,device1,device2";
    retArray =
        new String[] {
          "2020-01-01T00:00:05.000Z,2020-01-01T00:00:02.000Z,d2,d1,",
          "2020-01-01T00:00:05.000Z,2020-01-01T00:00:03.000Z,d2,d1,",
          "2020-01-01T00:00:07.000Z,2020-01-01T00:00:02.000Z,d2,d1,",
          "2020-01-01T00:00:07.000Z,2020-01-01T00:00:03.000Z,d2,d1,",
        };
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    expectedHeader = new String[] {"attr1", "attr2"};
    sql =
        "select t0.attr1,t0.attr2 from table0 t0 join table1 t1 on t0.attr1=t1.attr1 AND t0.attr2=t1.attr2";
    retArray =
        new String[] {
          "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,",
          "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "c,d,", "t,a,",
          "t,a,", "t,a,",
        };
    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);

    //    expectedHeader = new String[] {"device", "device", "attr1", "attr1", "date", "date"};
    //    sql =
    //        "select t0.device, t1.device, t0.attr1, t1.attr1, t0.date, t1.date from table0 t0 join
    // table1 t1 on t0.device=t1.device and t0.attr1=t1.attr1 OR t0.date=t1.date";
    //    retArray =
    //        new String[] {
    //          "d1,d1,c,c,null,2023-01-01,",
    //          "d1,d1,c,c,null,2023-01-01,",
    //          "d1,d1,c,c,null,2023-01-01,",
    //          "d1,d1,c,c,null,null,",
    //          "d1,d1,c,c,null,null,",
    //          "d1,d1,c,c,null,null,",
    //          "d1,d1,t,t,null,null,",
    //          "d1,d1,t,t,null,null,",
    //          "d1,d1,t,t,null,null,",
    //          "d2,d1,null,c,2023-01-01,2023-01-01,",
    //        };
    //    tableResultSetEqualTest(sql, expectedHeader, retArray, DATABASE_NAME);
  }
In this IT, table has more than one TAGs and Attributes.
integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBMultiTAGsWithAttributesTableIT.java