diff --git a/src/executor/ShowExecutor.cpp b/src/executor/ShowExecutor.cpp
index a3fdf0465ffb41160e1bd5b00774ff75c7d504cb..28f0fbd524c5c8d227ca3a38ebe880167b436f36 100644
--- a/src/executor/ShowExecutor.cpp
+++ b/src/executor/ShowExecutor.cpp
@@ -74,6 +74,7 @@ void ShowExecutor::execute() {
 void ShowExecutor::showHosts() {
     auto future = ectx()->getMetaClient()->listHosts();
     auto *runner = ectx()->rctx()->runner();
+    constexpr static char kNoValidPart[] = "No valid partition";
 
     auto cb = [this] (auto &&resp) {
         if (!resp.ok()) {
@@ -88,6 +89,13 @@ void ShowExecutor::showHosts() {
                                         "Leader distribution", "Partition distribution"};
         resp_ = std::make_unique<cpp2::ExecutionResponse>();
         resp_->set_column_names(std::move(header));
+        std::sort(hostItems.begin(), hostItems.end(), [](const auto& a, const auto& b) {
+            // sort with online/offline and ip
+            if (a.get_status() == b.get_status()) {
+                return a.hostAddr.ip < b.hostAddr.ip;
+            }
+            return a.get_status() < b.get_status();
+        });
 
         for (auto& item : hostItems) {
             std::vector<cpp2::ColumnValue> row;
@@ -109,7 +117,7 @@ void ShowExecutor::showHosts() {
             std::string leaders;
             for (auto& spaceEntry : item.get_leader_parts()) {
                 leaderCount += spaceEntry.second.size();
-                leaders += "space " + folly::to<std::string>(spaceEntry.first) + ": " +
+                leaders += spaceEntry.first + ": " +
                            folly::to<std::string>(spaceEntry.second.size()) + ", ";
             }
             if (!leaders.empty()) {
@@ -117,16 +125,20 @@ void ShowExecutor::showHosts() {
             }
 
             row[3].set_integer(leaderCount);
-            row[4].set_str(leaders);
 
             std::string parts;
             for (auto& spaceEntry : item.get_all_parts()) {
-                parts += "space " + folly::to<std::string>(spaceEntry.first) + ": " +
-                           folly::to<std::string>(spaceEntry.second.size()) + ", ";
+                parts += spaceEntry.first + ": " +
+                         folly::to<std::string>(spaceEntry.second.size()) + ", ";
             }
             if (!parts.empty()) {
                 parts.resize(parts.size() - 2);
+            } else {
+                // if there is no valid parition on a host at all
+                leaders = kNoValidPart;
+                parts = kNoValidPart;
             }
+            row[4].set_str(leaders);
             row[5].set_str(parts);
 
             rows.emplace_back();
diff --git a/src/executor/test/SchemaTest.cpp b/src/executor/test/SchemaTest.cpp
index 1e7f2479edcf4d3fa16e0d103440801c354e60af..e0f7272b08929d7b613367639a583163797e5c7e 100644
--- a/src/executor/test/SchemaTest.cpp
+++ b/src/executor/test/SchemaTest.cpp
@@ -54,7 +54,8 @@ TEST_F(SchemaTest, metaCommunication) {
         client->execute(query, resp);
         std::vector<std::tuple<std::string, std::string, std::string,
                                int, std::string, std::string>> expected {
-            {"127.0.0.1", std::to_string(gEnv->storageServerPort()), "online", 0, "", ""},
+            {"127.0.0.1", std::to_string(gEnv->storageServerPort()), "online", 0,
+             "No valid partition", "No valid partition"},
         };
         ASSERT_TRUE(verifyResult(resp, expected));
     }
@@ -667,7 +668,8 @@ TEST_F(SchemaTest, TTLtest) {
         client->execute(query, resp);
         std::vector<std::tuple<std::string, std::string, std::string,
                                int, std::string, std::string>> expected {
-            {"127.0.0.1", std::to_string(gEnv->storageServerPort()), "online", 0, "", ""},
+            {"127.0.0.1", std::to_string(gEnv->storageServerPort()), "online", 0,
+             "No valid partition", "No valid partition"},
         };
         ASSERT_TRUE(verifyResult(resp, expected));
     }