1. 什么是存取控制、 觸發器、 存儲過程 、 游標
?
- 存取控制
- 定義:存取控制是數據庫管理系統(DBMS)為保障數據安全性與完整性,對不同用戶訪問數據庫對象(如表、視圖等)的權限加以管理的機制。它借助定義用戶角色和權限,限制用戶對數據庫的操作,防止未授權訪問和數據泄露。
- 要點:包含用戶認證(確認用戶身份)、授權(賦予用戶特定操作權限,如查詢、插入、更新、刪除等)以及權限管理(可隨時修改用戶權限)。
- 應用:在多用戶的企業級數據庫系統中,依據員工的崗位和職責分配不同的數據庫操作權限。例如,財務人員可以查詢和修改財務數據,而普通員工只能查詢部分公開數據。
- Java 代碼示例(使用 JDBC 模擬用戶認證和授權):
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class AccessControlExample {public static void main(String[] args) {try {// 模擬用戶認證String username = "user1";String password = "password1";if (authenticateUser(username, password)) {// 模擬授權操作,這里假設用戶有查詢權限Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb", username, password);Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table");while (resultSet.next()) {System.out.println(resultSet.getString(1));}resultSet.close();statement.close();connection.close();}} catch (Exception e) {e.printStackTrace();}}public static boolean authenticateUser(String username, String password) {// 簡單模擬認證邏輯return "user1".equals(username) && "password1".equals(password);}
}
- 觸發器
- 定義:觸發器是一種特殊的存儲過程,會在數據庫發生特定事件(如插入、更新、刪除操作)時自動執行。它可用于實現復雜的業務規則和數據完整性約束。
- 要點:觸發器與特定表關聯,在表上的特定操作發生時觸發,可包含 SQL 語句和控制邏輯,能在操作前后執行。
- 應用:在電商系統中,當用戶下單時,觸發一個觸發器更新庫存表,減少相應商品的庫存數量。
- SQL 代碼示例(MySQL 觸發器):
sql
-- 創建一個表用于存儲訂單信息
CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY,product_id INT,quantity INT
);-- 創建一個表用于存儲商品庫存信息
CREATE TABLE inventory (product_id INT PRIMARY KEY,stock INT
);-- 創建觸發器,在插入訂單時更新庫存
DELIMITER //
CREATE TRIGGER update_inventory_after_order
AFTER INSERT ON orders
FOR EACH ROW
BEGINUPDATE inventorySET stock = stock - NEW.quantityWHERE product_id = NEW.product_id;
END //
DELIMITER ;
- 存儲過程
- 定義:存儲過程是一組預先編譯好的 SQL 語句集合,存儲在數據庫中,用戶可通過調用存儲過程來執行這些語句,它能接受參數并返回結果。
- 要點:提高代碼復用性和可維護性,減少網絡傳輸開銷(在數據庫服務器端執行),可實現復雜業務邏輯。
- 應用:在銀行系統中,可創建一個存儲過程用于計算客戶的利息,根據不同的存款類型和存款金額計算利息。
- SQL 代碼示例(MySQL 存儲過程):
sql
-- 創建一個存儲過程用于計算利息
DELIMITER //
CREATE PROCEDURE calculate_interest(IN principal DECIMAL(10, 2), IN rate DECIMAL(5, 2), IN time INT, OUT interest DECIMAL(10, 2))
BEGINSET interest = (principal * rate * time) / 100;
END //
DELIMITER ;-- 調用存儲過程
SET @interest = 0;
CALL calculate_interest(1000, 5, 1, @interest);
SELECT @interest;
- 游標
- 定義:游標是一種數據庫對象,用于在結果集中逐行移動,允許用戶對結果集中的每一行進行單獨處理。當 SQL 語句返回多行結果時,游標可方便地對這些結果進行遍歷和操作。
- 要點:游標需先聲明、打開、使用,最后關閉和釋放。使用時要注意資源管理,避免內存泄漏。
- 應用:在處理大量數據時,可使用游標逐行處理數據,例如對數據庫中的每一條記錄進行數據清洗。
- SQL 代碼示例(MySQL 游標):
sql
-- 創建一個表用于測試
CREATE TABLE test_table (id INT PRIMARY KEY,name VARCHAR(50)
);INSERT INTO test_table VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');-- 使用游標遍歷表中的記錄
DELIMITER //
CREATE PROCEDURE iterate_table()
BEGINDECLARE done INT DEFAULT 0;DECLARE v_id INT;DECLARE v_name VARCHAR(50);DECLARE cur CURSOR FOR SELECT id, name FROM test_table;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;OPEN cur;read_loop: LOOPFETCH cur INTO v_id, v_name;IF done THENLEAVE read_loop;END IF;-- 處理每一行數據,這里簡單打印SELECT CONCAT('ID: ', v_id, ', Name: ', v_name);END LOOP;CLOSE cur;
END //
DELIMITER ;-- 調用存儲過程
CALL iterate_table();
?
2. 如何實現數據庫安全
?
- 物理安全
- 定義:保護數據庫的物理設備,防止硬件損壞、自然災害、盜竊等情況導致數據丟失或泄露。
- 要點:將數據庫服務器置于安全機房,配備防火、防盜、防潮、防雷等設施;定期備份數據,并將備份存儲在不同物理位置。
- 應用:大型企業會將數據庫服務器存放在專業的數據中心,采用 RAID 技術提高數據冗余性,同時定期將數據備份到異地的數據中心。
- Java 代碼示例(簡單的文件備份模擬):
java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class DatabaseBackupExample {public static void main(String[] args) {try {File sourceFile = new File("path/to/your/database/file");File backupFile = new File("path/to/backup/database/file");FileInputStream fis = new FileInputStream(sourceFile);FileOutputStream fos = new FileOutputStream(backupFile);byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {fos.write(buffer, 0, bytesRead);}fis.close();fos.close();System.out.println("Database backup completed.");} catch (IOException e) {e.printStackTrace();}}
}
- 用戶認證和授權
- 定義:通過用戶名和密碼等方式驗證用戶身份,只有合法用戶才能訪問數據庫。同時,為不同用戶分配不同操作權限,限制用戶對數據庫的訪問范圍。
- 要點:采用強密碼策略,定期更換密碼;采用多因素認證(如短信驗證碼、指紋識別等)提高認證安全性。
- 應用:在在線銀行系統中,用戶登錄時需要輸入用戶名、密碼和短信驗證碼進行身份驗證,并且不同用戶角色(如普通用戶、管理員)具有不同的操作權限。
- Java 代碼示例(使用 JDBC 進行用戶認證):
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;public class UserAuthenticationExample {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.print("Enter username: ");String username = scanner.nextLine();System.out.print("Enter password: ");String password = scanner.nextLine();try {Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb", username, password);Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table");while (resultSet.next()) {System.out.println(resultSet.getString(1));}resultSet.close();statement.close();connection.close();} catch (Exception e) {System.out.println("Authentication failed.");}}
}
- 數據加密
- 定義:對數據庫中的敏感數據進行加密處理,即使數據被非法獲取,沒有解密密鑰也無法查看數據內容。
- 要點:可對整個數據庫或特定列、表進行加密,選擇合適的加密算法,如 AES 等。
- 應用:在醫療系統中,對患者的個人信息和病歷數據進行加密存儲,確保數據的安全性。
- Java 代碼示例(使用 AES 加密和解密):
java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Base64;public class DataEncryptionExample {public static void main(String[] args) throws Exception {String plainText = "Sensitive data";// 生成密鑰KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128);SecretKey secretKey = keyGenerator.generateKey();// 加密Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);System.out.println("Encrypted text: " + encryptedText);// 解密cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);System.out.println("Decrypted text: " + decryptedText);}
}
- 審計和監控
- 定義:記錄數據庫的所有操作,包括用戶登錄、數據查詢、插入、更新、刪除等,以便在發生安全事件時進行審計和追溯。同時,實時監控數據庫的活動,及時發現異常行為并采取措施。
- 要點:設置合理的審計規則,只記錄重要操作;使用監控工具對數據庫的性能、連接數等指標進行實時監控。
- 應用:在金融機構的數據庫系統中,對所有的資金交易操作進行審計記錄,以便在出現問題時進行調查。
- Java 代碼示例(簡單的日志記錄模擬):
java
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;public class DatabaseAuditExample {public static void main(String[] args) {try {Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb", "user", "password");Statement statement = connection.createStatement();String sql = "SELECT * FROM your_table";// 記錄操作日志logOperation(sql);statement.executeQuery(sql);statement.close();connection.close();} catch (Exception e) {e.printStackTrace();}}public static void logOperation(String operation) {try (PrintWriter writer = new PrintWriter(new FileWriter("database_audit.log", true))) {writer.println(System.currentTimeMillis() + ": " + operation);} catch (IOException e) {e.printStackTrace();}}
}
?
3. mysql 鎖機制
?
- 共享鎖(讀鎖)
- 定義:多個事務可同時對同一資源加共享鎖,用于讀取數據。加共享鎖后,其他事務可繼續加共享鎖,但不能加排他鎖,直到所有共享鎖被釋放。
- 要點:用于并發讀取數據,提高并發性能。在讀取數據時,使用?
SELECT ... LOCK IN SHARE MODE
?語句可加共享鎖。 - 應用:在電商系統中,多個用戶同時查看商品信息時,可使用共享鎖,提高系統的并發處理能力。
- SQL 代碼示例(MySQL 共享鎖):
sql
-- 會話 1
START TRANSACTION;
SELECT * FROM products WHERE product_id = 1 LOCK IN SHARE MODE;
-- 這里可以繼續執行其他操作
COMMIT;-- 會話 2
START TRANSACTION;
SELECT * FROM products WHERE product_id = 1 LOCK IN SHARE MODE;
-- 可以正常執行,因為共享鎖不互斥
COMMIT;
- 排他鎖(寫鎖)
- 定義:一個事務對資源加排他鎖后,其他事務不能再對該資源加任何類型的鎖,直到排他鎖被釋放。排他鎖用于修改數據,保證數據的一致性。
- 要點:在更新、刪除數據時,使用?
SELECT ... FOR UPDATE
?語句可加排他鎖。 - 應用:在銀行系統中,當用戶進行轉賬操作時,對涉及的賬戶記錄加排他鎖,防止其他事務同時修改該賬戶信息。
- SQL 代碼示例(MySQL 排他鎖):
sql
-- 會話 1
START TRANSACTION;
SELECT * FROM accounts WHERE account_id = 1 FOR UPDATE;
-- 進行賬戶更新操作
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
COMMIT;-- 會話 2
START TRANSACTION;
SELECT * FROM accounts WHERE account_id = 1 FOR UPDATE;
-- 會被阻塞,直到會話 1 的排他鎖釋放
COMMIT;
- 表級鎖
- 定義:對整個表加鎖,操作簡單,但并發性能較低。當一個事務對表加鎖后,其他事務不能對該表進行任何操作,直到鎖被釋放。
- 要點:在執行?
LOCK TABLES
?語句時可對表加鎖,使用?UNLOCK TABLES
?語句釋放鎖。 - 應用:在進行全量數據更新或批量操作時,可使用表級鎖,確保數據的一致性。
- SQL 代碼示例(MySQL 表級鎖):
sql
-- 會話 1
LOCK TABLES products WRITE;
-- 進行表的更新操作
UPDATE products SET price = price * 1.1;
UNLOCK TABLES;-- 會話 2
-- 在會話 1 釋放鎖之前,以下操作會被阻塞
SELECT * FROM products;
- 行級鎖
- 定義:只對需要操作的行加鎖,并發性能較高。不同事務可同時對不同的行進行操作,減少鎖的競爭。
- 要點:InnoDB 存儲引擎支持行級鎖,通過索引來實現。如果沒有使用索引,行級鎖會退化為表級鎖。
- 應用:在高并發的電商系統中,對商品庫存記錄使用行級鎖,不同用戶可以同時修改不同商品的庫存。
- SQL 代碼示例(MySQL 行級鎖):
sql
-- 會話 1
START TRANSACTION;
SELECT * FROM products WHERE product_id = 1 FOR UPDATE;
-- 進行行的更新操作
UPDATE products SET stock = stock - 1 WHERE product_id = 1;
COMMIT;-- 會話 2
START TRANSACTION;
SELECT * FROM products WHERE product_id = 2 FOR UPDATE;
-- 可以正常執行,因為操作的是不同的行
UPDATE products SET stock = stock - 1 WHERE product_id = 2;
COMMIT;
?
4. 項目中如何實現事務
?
- 使用數據庫的事務支持
- 定義:大多數數據庫都提供事務支持,通過?
BEGIN TRANSACTION
、COMMIT
?和?ROLLBACK
?語句來實現事務的開始、提交和回滾。 - 要點:在項目中,將需要作為一個事務處理的 SQL 語句放在?
BEGIN TRANSACTION
?和?COMMIT
?之間,若執行過程中出現異常,則執行?ROLLBACK
?語句回滾事務。 - 應用:在電商系統的訂單處理中,將訂單創建、庫存扣減、資金扣除等操作放在一個事務中,確保數據的一致性。
- SQL 代碼示例(MySQL 事務):
sql
START TRANSACTION;
-- 插入訂單記錄
INSERT INTO orders (order_id, product_id, quantity) VALUES (1, 1, 1);
-- 更新庫存
UPDATE inventory SET stock = stock - 1 WHERE product_id = 1;
-- 檢查是否有足夠的庫存
IF (SELECT stock FROM inventory WHERE product_id = 1) < 0 THENROLLBACK;
ELSECOMMIT;
END IF;
- 使用編程語言的事務管理機制
- 定義:許多編程語言的數據庫連接庫都提供事務管理接口,例如 Java 的 JDBC 提供?
Connection.setAutoCommit(false)
?方法開啟事務,Connection.commit()
?方法提交事務,Connection.rollback()
?方法回滾事務。 - 要點:在代碼中,將需要作為一個事務處理的數據庫操作封裝在一個事務塊中,通過捕獲異常來決定是否提交或回滾事務。
- 應用:在 Java Web 項目中,使用 JDBC 進行數據庫操作時,將業務邏輯相關的數據庫操作封裝在一個事務中。
- Java 代碼示例(使用 JDBC 實現事務):
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;public class TransactionExample {public static void main(String[] args) {Connection connection = null;Statement statement = null;try {connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb", "user", "password");connection.setAutoCommit(false);statement = connection.createStatement();// 插入訂單記錄statement.executeUpdate("INSERT INTO orders (order_id, product_id, quantity) VALUES (1, 1, 1)");// 更新庫存statement.executeUpdate("UPDATE inventory SET stock = stock - 1 WHERE product_id = 1");connection.commit();} catch (Exception e) {try {if (connection != null) {connection.rollback();}} catch (Exception ex) {ex.printStackTrace();}e.printStackTrace();} finally {try {if (statement != null) {statement.close();}if (connection != null) {connection.setAutoCommit(true);connection.close();}} catch (Exception e) {e.printStackTrace();}}}
}
?
5. 數據庫設計一般設計成第幾范式
?
-
第一范式(1NF)
- 定義:要求數據庫表的每一列都是不可再分的原子值,即表中的每個字段都應該是單一的值,不能包含多個值。
- 要點:確保表中的數據具有原子性,避免數據冗余和不一致性。
- 應用:在設計用戶信息表時,將用戶的聯系方式拆分為手機號碼、電子郵箱等單獨的字段,而不是將多個聯系方式放在一個字段中。
- SQL 代碼示例(符合 1NF 的表設計):
sql
CREATE TABLE users (user_id INT PRIMARY KEY,name VARCHAR(50),phone_number VARCHAR(20),email VARCHAR(50)
);
- 第二范式(2NF)
- 定義:在滿足第一范式的基礎上,要求表中的每一個非主屬性完全依賴于主鍵,而不是部分依賴于主鍵。
- 要點:消除非主屬性對主鍵的部分依賴,減少數據冗余。
- 應用:在設計訂單表時,將訂單信息和商品信息分開,避免商品信息因為訂單編號的不同而重復存儲。
- SQL 代碼示例(符合 2NF 的表設計):
sql
-- 訂單表
CREATE TABLE orders (order_id INT PRIMARY KEY,user_id INT,order_date DATE,FOREIGN KEY (user_id) REFERENCES users(user_id)
);-- 訂單商品表
CREATE TABLE order_items (order_item_id INT PRIMARY KEY,order_id INT,product_id INT,quantity INT,FOREIGN KEY (order_id) REFERENCES orders(order_id),FOREIGN KEY (product_id) REFERENCES products(product_id)
);
- 第三范式(3NF)
- 定義:在滿足第二范式的基礎上,要求表中的每一個非主屬性都不傳遞依賴于主鍵。
- 要點:消除非主屬性對主鍵的傳遞依賴,進一步減少數據冗余。
- 應用:在設計員工信息表時,將部門信息單獨存儲在一個部門表中,避免員工信息因為部門編號的不同而重復存儲部門名稱等信息。
- SQL 代碼示例(符合 3NF 的表設計):
sql
-- 員工表
CREATE TABLE employees (employee_id INT PRIMARY KEY,name VARCHAR(50),department_id INT,FOREIGN KEY (department_id) REFERENCES departments(department_id)
);-- 部門表
CREATE TABLE departments (department_id INT PRIMARY KEY,department_name VARCHAR(50)
);
?
6. mysql 用的什么版本,5.7 跟 5.6 有啥區別
?
- 性能優化
- 定義:MySQL 5.7 在性能方面進行了諸多優化,例如引入多線程復制、改進查詢優化器等,以提高數據庫的處理能力和響應速度。
- 要點:多線程復制可提高主從復制的性能,減少復制延遲;查詢優化器能更智能地選擇執行計劃,提高查詢性能。
- 應用:在高并發的電商系統中,使用 MySQL 5.7 的多線程復制可以更快地將主庫的數據同步到從庫,確保數據的一致性。
- SQL 代碼示例(無特定代碼,可通過性能測試對比):
sql
-- 可以使用 EXPLAIN 分析查詢語句的執行計劃
EXPLAIN SELECT * FROM products WHERE category = 'electronics';
- 安全性增強
- 定義:MySQL 5.7 增強了安全性,引入更嚴格的密碼策略、支持角色管理等,以保護數據庫免受非法訪問和攻擊。
- 要點:新的密碼策略要求用戶使用更復雜的密碼,提高密碼的安全性;角色管理可更方便地管理用戶的權限。
- 應用:在企業級數據庫系統中,使用 MySQL 5.7 的角色管理功能可以根據員工的崗位和職責分配不同的數據庫操作權限。
- SQL 代碼示例(創建角色和分配權限):
sql
-- 創建角色
CREATE ROLE 'read_only_role';
-- 授予角色查詢權限
GRANT SELECT ON your_database.* TO 'read_only_role';
-- 創建用戶并分配角色
CREATE USER 'new_user'@'localhost' IDENTIFIED BY 'password';
GRANT 'read_only_role' TO 'new_user'@'localhost';
- 功能增強
- 定義:MySQL 5.7 增加了一些新功能,例如 JSON 數據類型、窗口函數等,以滿足更復雜的業務需求。
- 要點:JSON 數據類型可方便地存儲和查詢 JSON 格式的數據;窗口函數可在不使用子查詢的情況下進行復雜的分析查詢。
- 應用:在社交網絡系統中,使用 JSON 數據類型存儲用戶的個性化設置信息;使用窗口函數分析用戶的活躍度排名。
- SQL 代碼示例(JSON 數據類型和窗口函數):
sql
-- 創建包含 JSON 字段的表
CREATE TABLE users (user_id INT PRIMARY KEY,name VARCHAR(50),settings JSON
);-- 插入 JSON 數據
INSERT INTO users (user_id, name, settings) VALUES (1, 'Alice', '{"theme": "dark", "notifications": true}');-- 查詢 JSON 數據
SELECT user_id, name, settings->'$.theme' AS theme FROM users;-- 使用窗口函數計算排名
SELECT product_id, price, RANK() OVER (ORDER BY price DESC) AS price_rank FROM products;
?
7. 有一個表 (三個字段:姓名, id, 分數) 要求查出平均分大于 80 的 id 然后分數降序排序。
?
sql
-- 假設表名為 student_scores
SELECT id
FROM student_scores
GROUP BY id
HAVING AVG(分數) > 80
ORDER BY 分數 DESC;
- 定義:通過?
GROUP BY
?對?id
?進行分組,使用?AVG
?函數計算每個?id
?的平均分,HAVING
?篩選出平均分大于 80 的?id
,最后使用?ORDER BY
?按分數降序排序。 - 要點:
GROUP BY
?用于分組,HAVING
?用于篩選分組后的結果,ORDER BY
?用于排序。 - 應用:在學校的成績管理系統中,篩選出平均分優秀的學生的?
id
,以便進行獎勵。
?
8. 為什么 mysql 事務能保證失敗回滾
?
- 定義
MySQL 的事務通過日志系統(如 InnoDB 的 redo log 和 undo log)來保證失敗回滾。當一個事務開始時,MySQL 會記錄所有的操作到 undo log 中。如果事務執行過程中出現錯誤,MySQL 會根據 undo log 中的記錄將數據恢復到事務開始前的狀態。同時,redo log 用于在數據庫崩潰后恢復數據,保證事務的持久性。
- 要點
- undo log 是實現事務回滾的關鍵,它記錄了事務對數據的修改操作,以便在需要時進行反向操作。
- redo log 保證了事務的持久性,即使數據庫崩潰,也可以通過 redo log 恢復到崩潰前的狀態。
- 應用
在銀行轉賬系統中,如果在轉賬過程中出現系統故障,事務可以回滾,保證資金的安全。
SQL 代碼示例(模擬事務回滾)
sql
START TRANSACTION;
-- 模擬轉賬操作
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
-- 模擬出現錯誤
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Simulated error';
ROLLBACK;
?
9. 已知學生表, 成績表, 如何查找學生總成績大于 500 的學生的姓名跟總分
?
假設學生表名為?students
,包含字段?id
?和?name
;成績表名為?scores
,包含字段?student_id
?和?score
。
sql
SELECT s.name, SUM(sc.score) AS total_score
FROM students s
JOIN scores sc ON s.id = sc.student_id
GROUP BY s.id, s.name
HAVING SUM(sc.score) > 500;
- 定義:通過?
JOIN
?將學生表和成績表關聯,使用?GROUP BY
?按學生的?id
?和?name
?分組,SUM
?計算每個學生的總成績,HAVING
?篩選出總成績大于 500 的學生。 - 要點:
JOIN
?用于關聯兩個表,GROUP BY
?用于分組,SUM
?用于計算總成績,HAVING
?用于篩選分組后的結果。 - 應用:在學校的成績統計系統中,查找總成績優秀的學生,以便進行表彰。
?
10. 在一個整形數組中, 找出第三大的數, 注意時間效率
?
java
import java.util.TreeSet;public class ThirdLargestNumber {public static int thirdLargest(int[] nums) {TreeSet<Integer> set = new TreeSet<>();for (int num : nums) {set.add(num);if (set.size() > 3) {set.pollFirst();}}return set.size() < 3 ? set.last() : set.first();}public static void main(String[] args) {int[] nums = {3, 2, 1, 5, 6, 4};System.out.println(thirdLargest(nums));}
}
- 定義:使用?
TreeSet
?存儲數組元素,TreeSet
?會自動排序。遍歷數組,將元素添加到?TreeSet
?中,若?TreeSet
?大小超過 3,則移除最小元素。最后根據?TreeSet
?大小返回相應結果。 - 要點:
TreeSet
?可自動排序,pollFirst()
?移除最小元素,last()
?獲取最大元素,first()
?獲取最小元素。 - 應用:在游戲排行榜系統中,找出排名第三的玩家分數。該算法時間復雜度為?\(O(n log k)\),其中?n?是數組長度,k?是要找的第?k?大的數(這里?\(k = 3\))。若要找出第?k?大的數,可將?
TreeSet
?大小限制改為?k。
?
?友情提示:本文已經整理成文檔,可以到如下鏈接免積分下載閱讀
https://download.csdn.net/download/ylfhpy/90567215?