對 ChatGPT 做一次技術面試(ChatGPT 沒能透過)

捏造的信仰發表於2023-02-10

將 ChatGPT 當作一個求職者來面試它,它的表現如何?下面是要求它做一個資料庫設計的例子。

:對一個系統的描述如下:
系統中有大量註冊使用者,使用者可以關注其他使用者。使用者可以釋出訊息,訊息包含釋出者、釋出時間和可見性。訊息的可見性可以是公開、不公開或僅對關注自己的使用者可見。
請設計這個系統的資料庫表。

ChatGPT:下面是一種資料庫表的設計:

1.使用者表 (User)

id: 使用者的唯一標識(主鍵)
username: 使用者名稱
password: 密碼
email: 電子郵件地址

2.關注表 (Follow)

id: 關注記錄的唯一標識(主鍵)
user_id: 關注者的使用者ID(外來鍵,關聯到User表的id欄位)
follow_id: 被關注者的使用者ID(外來鍵,關聯到User表的id欄位)

3.訊息表 (Message)

id: 訊息的唯一標識(主鍵)
user_id: 訊息釋出者的使用者ID(外來鍵,關聯到User表的id欄位)
content: 訊息內容
visibility: 訊息的可見性(公開/不公開/僅對關注自己的使用者可見)
created_at: 訊息釋出的時間戳

請注意,這只是一種可能的資料庫表設計,具體的實現可能因為需求的不同而有所變化。


:請給出這些表的建表 SQL 語句。

ChatGPT:以下是用 SQL 建立上述表的語句:

CREATE TABLE User (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);

CREATE TABLE Follow (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    follow_id INT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES User(id),
    FOREIGN KEY (follow_id) REFERENCES User(id)
);

CREATE TABLE Message (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    content TEXT NOT NULL,
    visibility ENUM('public', 'private', 'followers') NOT NULL,
    created_at TIMESTAMP NOT NULL,
    FOREIGN KEY (user_id) REFERENCES User(id)
);

請注意,上述 SQL 語句是在 MySQL 中建立表的語句。如果使用其他資料庫系統,可能需要更改語法。


:請給出用MyBatis框架查詢User表的Java程式碼

ChatGPT:下面是一種使用 MyBatis 框架查詢 User 表的 Java 程式碼:

1.首先,需要在 User 實體類中定義屬性:

public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;
    // 省略 getters 和 setters
}

2.其次,需要在 MyBatis 的對映檔案中編寫 SQL 語句:

<select id="getUserById" resultType="User">
    SELECT * FROM User WHERE id = #{id}
</select>

3.最後,在 Java 程式碼中呼叫 MyBatis 查詢:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.getUserById(1);
    System.out.println(user);
} finally {
    sqlSession.close();
}

請注意,這僅僅是一個簡單的示例,實際的程式碼可能會有所不同。還需要配置 MyBatis,建立 SqlSessionFactory 物件等。


接下來提升難度。

:現在需求改了,要求使用者發訊息可以指定接收人,此時資料庫設計要如何改?

ChatGPT:現在需要考慮使用者發訊息可以指定接收人,因此可以建立一個新的表,儲存訊息和接收人之間的關係。

1.首先,建立一個新表 MessageReceiver:

CREATE TABLE MessageReceiver (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message_id INT NOT NULL,
    receiver_id INT NOT NULL,
    FOREIGN KEY (message_id) REFERENCES Message(id),
    FOREIGN KEY (receiver_id) REFERENCES User(id)
);

2.然後,將 Message 表的 visibility 欄位刪除:

ALTER TABLE Message DROP COLUMN visibility;

3.最後,可以使用兩種方式之一在 MyBatis 中查詢訊息:

查詢所有與特定使用者相關的訊息:
<select id="getMessagesByReceiverId" resultType="Message">
    SELECT m.* FROM Message m
    INNER JOIN MessageReceiver mr ON m.id = mr.message_id
    WHERE mr.receiver_id = #{receiverId}
</select>
查詢特定使用者傳送的所有訊息:
<select id="getMessagesBySenderId" resultType="Message">
    SELECT * FROM Message WHERE user_id = #{senderId}
</select>

這樣,您就可以根據訊息的傳送者和接收者的不同需求,選擇不同的查詢方法了。


(注意上面的回答存在問題,刪除 visibility 欄位的操作是我沒想到的,於是我接著問)

:但是 visibility 欄位刪除後,如何表達一個訊息是公開的呢?

ChatGPT:如果刪除了 visibility 欄位,可以透過在 MessageReceiver 表中為所有使用者新增一條記錄來表示訊息是公開的。

1.首先,建立一個新的角色 PUBLIC:

CREATE TABLE Role (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

INSERT INTO Role (name) VALUES ('PUBLIC');

2.然後,建立一個新的表 UserRole,用於儲存使用者和角色之間的關係:

CREATE TABLE UserRole (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    role_id INT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES User(id),
    FOREIGN KEY (role_id) REFERENCES Role(id)
);

3.最後,為所有使用者新增一條記錄,表示他們是公共使用者:

INSERT INTO UserRole (user_id, role_id)
SELECT id, (SELECT id FROM Role WHERE name = 'PUBLIC')
FROM User;

現在,您可以使用以下查詢語句查詢公開訊息:

<select id="getPublicMessages" resultType="Message">
    SELECT m.* FROM Message m
    INNER JOIN MessageReceiver mr ON m.id = mr.message_id
    INNER JOIN UserRole ur ON mr.receiver_id = ur.user_id
    WHERE ur.role_id = (SELECT id FROM Role WHERE name = 'PUBLIC')
</select>

這樣,您就可以使用相同的資料庫表來表示公開訊息了。


(不錯不錯,雖然這個回答還是有問題,但基本上還是可以說讓它給圓回去了。正確的回答是建立一個使用者用來表示“公開接收者”即可。現在我換個表達的角度提問,看它能不能充分理解)

:按照需求,如果一條訊息是公開的,那麼它就不應該再有其它的接收人。請給出查詢違反這條規則的訊息記錄的SQL語句。

ChatGPT:您可以使用以下 SQL 語句查詢違反這條規則的訊息記錄:

SELECT m.*
FROM Message m
INNER JOIN MessageReceiver mr ON m.id = mr.message_id
INNER JOIN UserRole ur ON mr.receiver_id = ur.user_id
WHERE ur.role_id != (SELECT id FROM Role WHERE name = 'PUBLIC')
GROUP BY m.id
HAVING COUNT(ur.id) > 1;

此查詢語句查詢所有具有不止一個接收人的訊息,並且這些接收人中必須至少有一個不是公共使用者。如果一條訊息同時具有公共使用者和其他接收人,則該訊息是違反規則的。


(上面的回答是有問題的,它在後面準確的描述了 SQL 的邏輯,但 SQL 本身存在問題,於是我希望它能糾正這個問題)

:發給多個接收人的非公開訊息同樣會被這個SQL查詢出來,但是這樣的訊息沒有違反規則。

ChatGPT:您對我的回答是正確的。我錯誤地認為發給多個接收人的訊息是違反規則的。以下是修正後的 SQL 語句:

SELECT m.*
FROM Message m
INNER JOIN MessageReceiver mr ON m.id = mr.message_id
INNER JOIN UserRole ur ON mr.receiver_id = ur.user_id
WHERE m.visibility = (SELECT id FROM Visibility WHERE name = 'PUBLIC') AND
      COUNT(ur.id) > 1;

此語句只查詢 visibility 欄位為“公開”的訊息,但有多個接收人的記錄。


(這個回答問題更嚴重了,因為 visibility 欄位在需求變更後已經沒了。我懷疑我沒表達清楚,於是繼續追加條件)

:visibility欄位不是被刪了嗎,怎麼SQL裡面又出現了?請按照需求變更後的表設計來生成SQL語句。

ChatGPT:對不起,我錯誤地在 SQL 語句中提到了 visibility 欄位。根據需求變更後的表設計,可以使用以下 SQL 語句來查詢具有多個接收人的非公開訊息:

SELECT m.*
FROM Message m
INNER JOIN MessageReceiver mr ON m.id = mr.message_id
GROUP BY m.id
HAVING COUNT(mr.receiver_id) > 1;

這條語句將查詢出所有具有多個接收人的非公開訊息。

(這個回答問題更嚴重了,它似乎忘掉了我之前規則中的公開訊息條件,而且 SQL 內容與後面的描述都不一致了。至此我推測 ChatGPT 對上下文的“記憶”只能維持少數回合,再繼續問下去也沒有含義了。面試結束。)

相關文章