MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)批量表分區(qū)完整示例
對(duì)于單表大數(shù)據(jù)量大的問題,如果數(shù)據(jù)支持分片,使用表分區(qū)是個(gè)不錯(cuò)的選擇,那么MySQL是如何實(shí)現(xiàn)表分區(qū)的?
一、表分區(qū)條件
1.數(shù)據(jù)庫(kù)存儲(chǔ)引擎支持:InnoDB 和 MyISAM引擎
2.數(shù)據(jù)庫(kù)版本支持:MySQL 5.1以后(版本不同,具體的特性支持可能會(huì)有所不同)
3.數(shù)據(jù)必須有一個(gè)或多個(gè)分區(qū)鍵:作為分區(qū)的鍵(字段)必須是主鍵的一部分(聯(lián)合主鍵)
4.分區(qū)定義:每個(gè)分區(qū)必須明確地定義數(shù)據(jù)范圍
5.分區(qū)維護(hù):隨著時(shí)間推移,可能需要添加新的分區(qū)或刪除舊的分區(qū),以保持?jǐn)?shù)據(jù)庫(kù)的性能和結(jié)構(gòu)
二、常規(guī)表和分區(qū)表的區(qū)別
常規(guī)表和分區(qū)表對(duì)比
| 常規(guī)表 | 分區(qū)表 | |
|---|---|---|
| 數(shù)據(jù)結(jié)構(gòu) | 所有數(shù)據(jù)存儲(chǔ)在單一數(shù)據(jù)文件 | 數(shù)據(jù)被邏輯上分成多個(gè)部分,可能存放在多個(gè)文件甚至多個(gè)磁盤 |
| 查詢優(yōu)化 | 查詢時(shí)默認(rèn)掃描整表數(shù)據(jù) | 只訪問相關(guān)分區(qū)數(shù)據(jù) |
| I/O操作 | 添加、刪除或修改行操作直接作用于整表 | 只對(duì)單個(gè)分區(qū)操作,不影響其他分區(qū)數(shù)據(jù) |
| 備份恢復(fù) | 通常備份整表數(shù)據(jù) | 可以單獨(dú)備份或恢復(fù)特定分區(qū) |
| 存儲(chǔ)管理 | 所有數(shù)據(jù)集中存儲(chǔ) | 數(shù)據(jù)分散到多個(gè)分區(qū) |
| 擴(kuò)展性 | 隨著數(shù)據(jù)量增長(zhǎng),可能會(huì)遇到性能瓶頸 | 更容易水平擴(kuò)展,可以通過增加新分區(qū)來(lái)處理更大的數(shù)據(jù)集,而不需要改變應(yīng)用程序邏輯 |
| 限值和復(fù)雜性 | 相對(duì)簡(jiǎn)單,沒有特殊的創(chuàng)建或維護(hù)要求 | 設(shè)計(jì)和實(shí)現(xiàn)更加復(fù)雜,需要考慮如何正確地設(shè)置分區(qū)策略以滿足業(yè)務(wù)需求 |
從上面看分區(qū)表是否有很大的優(yōu)勢(shì)?但是同樣分區(qū)表也存在一些限值:
分區(qū)表的限制
| 常規(guī)表 | 分區(qū)表 | |
|---|---|---|
| 外鍵約束 | √ | × |
| 全文索引 | √ | ×(5.6以前版本) ?(5.6以后版本) |
| 臨時(shí)表 | √ | × |
| 列修改 | √ | × |
| 特定的ALTER TABLE語(yǔ)句 | √ | ×(修改主鍵、唯一鍵等) |
| 性能影響 | 數(shù)據(jù)量影響 | 添加、刪除、合并表分區(qū),可能會(huì)導(dǎo)致鎖表從而影響性能 |
| 備份和恢復(fù)工具支持 | 通常工具都支持 | 不是所有的備份和恢復(fù)工具都完全支持分區(qū)表的所有特性 |
| 主備服務(wù)器數(shù)據(jù)復(fù)制 | 無(wú)特殊要求 | 必須保證分區(qū)規(guī)則一致性,任何不匹配都可能導(dǎo)致復(fù)制失敗或數(shù)據(jù)不一致 |
| 分區(qū)類型限制 | 無(wú) | 存儲(chǔ)引擎可能限制分區(qū)類型 |
| 查詢優(yōu)化器的行為 | 簡(jiǎn)單索引 | 表分區(qū)+索引,特情情況的復(fù)雜查詢可能會(huì)有表分區(qū)裁剪失效問題 |
三、表分區(qū)的創(chuàng)建
表分區(qū)創(chuàng)建關(guān)鍵的三個(gè)點(diǎn):創(chuàng)建表、設(shè)置分區(qū)鍵、設(shè)置分片策略
示例:
CREATE TABLE sales (
id INT NOT NULL,
sale_date DATE NOT NULL,
amount DECIMAL(10,2)
)
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p0 VALUES LESS THAN (2020),
PARTITION p1 VALUES LESS THAN (2021),
PARTITION p2 VALUES LESS THAN (2022),
PARTITION p3 VALUES LESS THAN MAXVALUE
);創(chuàng)建表名:sales
分區(qū)鍵:sale_date字段的year()結(jié)果,即sale_date字段的年份
分片策略:p0分區(qū)存儲(chǔ)小于2020年數(shù)據(jù)、 p1分區(qū)存儲(chǔ)小于2021年數(shù)據(jù)、p2分區(qū)存儲(chǔ)小于2022年數(shù)據(jù)、p3分區(qū)存儲(chǔ)其他年份數(shù)據(jù)(注意:這里的數(shù)據(jù)“擋板”很重要,設(shè)置時(shí)一定要小心)
注意:這里的分片策略是“LESS THAN xxx”,表示小于后面策略的數(shù)據(jù)數(shù)據(jù),如上面就是小于指定年份的數(shù)據(jù)歸屬于這個(gè)分區(qū),因此上面用“數(shù)據(jù)擋板”這個(gè)詞
四、將既有表轉(zhuǎn)換分區(qū)表腳本
因?yàn)楸淼膭?chuàng)建結(jié)構(gòu)不同,因此既有表不能直接轉(zhuǎn)換為分區(qū)表,要實(shí)現(xiàn)既有表轉(zhuǎn)換為分區(qū)表,需要經(jīng)過以下幾步:
1.根據(jù)既有表創(chuàng)建同字段結(jié)構(gòu)的新分區(qū)表、定義好相關(guān)分區(qū)策略
2.遷移數(shù)據(jù)到分區(qū)表
3.刪除舊表、并將分區(qū)表改名為原表
具體實(shí)現(xiàn)腳本如下:
CREATE DEFINER=`root`@`%` PROCEDURE `convert_table_to_partition`(IN tbl_name VARCHAR(200),OUT out_status INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
-- 輸出狀態(tài),開始執(zhí)行狀態(tài) 100,執(zhí)行成功狀態(tài) 200,執(zhí)行失敗狀態(tài) 50
SET out_status = 100;
-- 創(chuàng)建一個(gè)新的空表,不包含表分區(qū)(要轉(zhuǎn)換為分區(qū)表,必須是空表)
SET @create_empty_tbl_sql = CONCAT(
'CREATE TABLE ', tbl_name, '_partitioned LIKE ', tbl_name, ';'
);
PREPARE stmt FROM @create_empty_tbl_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 獲取所有唯一的 year_no 和 month_no 組合作為構(gòu)建分區(qū)定義分區(qū)鍵
SET @partition_def = '';
SET @query = CONCAT(
'SELECT GROUP_CONCAT(
CONCAT("PARTITION p_", year_no, "_", LPAD(month_no, 2, "0"),
" VALUES LESS THAN (",
CASE WHEN month_no = 12 THEN year_no + 1 ELSE year_no END, ", ",
CASE WHEN month_no = 12 THEN 1 ELSE month_no + 1 END, ")")
ORDER BY year_no, month_no SEPARATOR ",\n"
) INTO @partition_def
FROM (
SELECT DISTINCT year_no, month_no
FROM ', tbl_name, '
ORDER BY year_no, month_no
) AS unique_years_months;'
);
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 調(diào)試信息:輸出分區(qū)定義字符串
--SELECT tbl_name,@partition_def;
-- 檢查是否有有效的分區(qū)定義
IF @partition_def IS NULL OR @partition_def = '' THEN
SELECT tbl_name,'No data found for partitioning. Skipping partition creation and data migration.';
-- 空表則直接添加 p_max 分區(qū)用于捕獲未來(lái)數(shù)據(jù)
SET @partition_def = '\nPARTITION p_max VALUES LESS THAN (MAXVALUE, MAXVALUE)';
ELSE
-- 添加 p_max 分區(qū)用于捕獲未來(lái)數(shù)據(jù)
SET @partition_def = CONCAT(@partition_def, ',\nPARTITION p_max VALUES LESS THAN (MAXVALUE, MAXVALUE)');
END IF;
-- 使用 ALTER TABLE 添加分區(qū)定義
SET @add_partitions_sql = CONCAT(
'ALTER TABLE ', tbl_name, '_partitioned
PARTITION BY RANGE COLUMNS(year_no, month_no) (', @partition_def, ');'
);
-- 調(diào)試信息:輸出添加分區(qū)的 SQL 語(yǔ)句
--SELECT tbl_name,@add_partitions_sql;
PREPARE stmt FROM @add_partitions_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 遷移數(shù)據(jù)到新的分區(qū)表
SET @insert_into_partitioned_sql = CONCAT(
'INSERT INTO ', tbl_name, '_partitioned SELECT * FROM ', tbl_name, ';'
);
-- 調(diào)試信息:輸出插入數(shù)據(jù)的 SQL 語(yǔ)句
-- SELECT tbl_name,@insert_into_partitioned_sql;
PREPARE stmt FROM @insert_into_partitioned_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 驗(yàn)證數(shù)據(jù)遷移是否成功
SET @count_original = CONCAT('SELECT COUNT(*) INTO @count_original FROM ', tbl_name);
PREPARE stmt FROM @count_original;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @count_partitioned = CONCAT('SELECT COUNT(*) INTO @count_partitioned FROM ', tbl_name, '_partitioned');
PREPARE stmt FROM @count_partitioned;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 比較原表和新分區(qū)表的數(shù)據(jù)行數(shù)
-- SELECT tbl_name,@count_original, @count_partitioned;
-- 如果數(shù)據(jù)遷移成功,刪除舊表并重命名新表(無(wú)論是否有數(shù)據(jù),均刪除緩存表)
IF @count_original = @count_partitioned THEN
-- 刪除舊表
SET @drop_old_table_sql = CONCAT('DROP TABLE IF EXISTS ', tbl_name);
PREPARE stmt FROM @drop_old_table_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 重命名新表為舊表名
SET @rename_tables_sql = CONCAT('RENAME TABLE ', tbl_name, '_partitioned TO ', tbl_name);
PREPARE stmt FROM @rename_tables_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- SELECT tbl_name,'Table conversion and data migration completed successfully.';
SET out_status = 200;
ELSE
-- SELECT tbl_name,'Data migration failed, check the logs for more information.';
SET out_status = 50;
END IF;
END上面腳本是一個(gè)完整的將既有表轉(zhuǎn)換為以“year_no”和“month_no”字段為分區(qū)鍵的分區(qū)表,主要有以下幾步操作:
1)以既有表為模板創(chuàng)建一個(gè)新的空表,不包含表分區(qū)(要轉(zhuǎn)換為分區(qū)表,必須是空表)
2)獲取所有唯一的 year_no 和 month_no 組合并構(gòu)建分區(qū)定義字符串(對(duì)既有數(shù)據(jù)分析需要?jiǎng)澐值姆謪^(qū)策略)
3)檢查是否有效的分區(qū)定義,若無(wú)分區(qū)定義,強(qiáng)烈建議則創(chuàng)建一個(gè)默認(rèn)的分區(qū)策略p_max以存儲(chǔ)未來(lái)的數(shù)據(jù)
4)更新空表,添加相關(guān)的分區(qū)策略
5)遷移歷史數(shù)據(jù)到分區(qū)表
6)數(shù)據(jù)遷移校驗(yàn)(驗(yàn)證數(shù)據(jù)完整性)
7)刪除舊表(回收表名)
8)將新分區(qū)表改名為原表名
五、批量轉(zhuǎn)換表為分區(qū)表
批量將常規(guī)表轉(zhuǎn)換為分區(qū)表,具體腳本如下:
CREATE DEFINER=`root`@`%` PROCEDURE `tables_convert_to_partition`()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl_name VARCHAR(64);
DECLARE convert_status INT;
DECLARE cur CURSOR FOR
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE 'ai_result_%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO tbl_name;
IF done THEN
LEAVE read_loop;
END IF;
-- 調(diào)試信息:輸出正在轉(zhuǎn)換的表
SELECT tbl_name,'covering...';
CALL convert_table_to_partition(tbl_name,@status);
SET convert_status = @status;
-- 根據(jù)返回的狀態(tài)進(jìn)行相應(yīng)的處理
CASE convert_status
WHEN 100 THEN
-- 開始狀態(tài),可以忽略,因?yàn)檫@是預(yù)期的初始狀態(tài)
SELECT tbl_name, 'Started conversion.';
WHEN 200 THEN
-- 成功完成
SELECT tbl_name, 'Conversion and data migration completed successfully.';
WHEN 50 THEN
-- 失敗
SELECT tbl_name, 'Data migration failed. Check the logs for more information.';
ELSE
-- 未知狀態(tài)
SELECT tbl_name, CONCAT('Unknown status: ', status);
END CASE;
END LOOP;
CLOSE cur;
END這里是以“ai_result_”開頭的表為例,將所有相關(guān)表轉(zhuǎn)換為分區(qū)表,在執(zhí)行這個(gè)存儲(chǔ)過程時(shí),操作用戶必須要有information_schema數(shù)據(jù)庫(kù)讀取權(quán)限,這樣才能查詢出相關(guān)的表名從而進(jìn)行轉(zhuǎn)換。
該腳本建議為一次性執(zhí)行腳本,避免對(duì)標(biāo)頻繁轉(zhuǎn)換,防止鎖表(因此表名前綴已固定在代碼中,需根據(jù)自身需求修改)
六、表分區(qū)維護(hù):添加表分區(qū)
表分區(qū)經(jīng)過上面的過程創(chuàng)建,理論上已經(jīng)對(duì)歷史數(shù)據(jù)進(jìn)行表分區(qū),對(duì)未來(lái)數(shù)據(jù)也能存儲(chǔ)到p_max分區(qū),但是p_max分區(qū)數(shù)據(jù)如果不進(jìn)行維護(hù),同樣會(huì)有數(shù)據(jù)量過大問題,因此我們需要定期切割p_max分區(qū)并增加相關(guān)表分區(qū),這個(gè)操作需要在數(shù)據(jù)進(jìn)入之前執(zhí)行,具體執(zhí)行腳本如下:
CREATE DEFINER=`root`@`%` PROCEDURE `add_monthly_partitions`(IN tbl_name VARCHAR(64), IN year_no INT, IN month_no INT,OUT out_status INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
-- 輸出狀態(tài),開始執(zhí)行狀態(tài) 100,執(zhí)行成功狀態(tài) 200,執(zhí)行失敗狀態(tài) 50
SET out_status = 100;
-- 檢查待添加的分區(qū)是否已經(jīng)存在
SET @partition_exists = EXISTS (SELECT 1 FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = tbl_name
AND PARTITION_NAME = CONCAT('p_', year_no, '_', LPAD(month_no, 2, '0')));
IF @partition_exists THEN
-- 如果分區(qū)已存在,直接返回消息
-- SELECT CONCAT('Partition p_', year_no, '_', LPAD(month_no, 2, '0'), ' already exists. No action taken.') AS message;
SET out_status = 200;
ELSE
-- 檢查表中是否已經(jīng)存在 p_max 分區(qū)
SET @has_p_max = EXISTS (SELECT 1 FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = tbl_name
AND PARTITION_NAME = 'p_max');
-- 構(gòu)建添加分區(qū)的 SQL 語(yǔ)句
IF @has_p_max THEN
-- 如果存在 p_max 分區(qū),則重新組織分區(qū),將 p_max 分割成新分區(qū)和更新后的 p_max
SET @reorganize_partition_sql = CONCAT(
'ALTER TABLE ', tbl_name, ' REORGANIZE PARTITION p_max INTO (
PARTITION p_', year_no, '_', LPAD(month_no, 2, '0'),
' VALUES LESS THAN (',
CASE WHEN month_no = 12 THEN year_no + 1 ELSE year_no END, ', ',
CASE WHEN month_no = 12 THEN 1 ELSE month_no + 1 END, '),
PARTITION p_max VALUES LESS THAN (MAXVALUE, MAXVALUE)
)'
);
PREPARE stmt FROM @reorganize_partition_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- SELECT CONCAT('Partition p_', year_no, '_', LPAD(month_no, 2, '0'), ' and updated p_max added successfully.') AS message;
SET out_status = 200;
ELSE
-- 如果不存在 p_max 分區(qū),則直接添加新分區(qū)
SET @add_partition_sql = CONCAT(
'ALTER TABLE ', tbl_name, ' ADD PARTITION (
PARTITION p_', year_no, '_', LPAD(month_no, 2, '0'),
' VALUES LESS THAN (',
CASE WHEN month_no = 12 THEN year_no + 1 ELSE year_no END, ', ',
CASE WHEN month_no = 12 THEN 1 ELSE month_no + 1 END, ')
)'
);
PREPARE stmt FROM @add_partition_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- SELECT CONCAT('Partition p_', year_no, '_', LPAD(month_no, 2, '0'), ' added successfully.') AS message;
SET out_status = 200;
END IF;
END IF;
END上面腳本的執(zhí)行過程如下:
1)檢測(cè)待添加的分區(qū)是否已存在(已存在則不添加,不存在才添加)
2)檢測(cè)表中是否存在p_max 分區(qū)(檢測(cè)待切割分區(qū),若存在則切割分區(qū),若不存在這創(chuàng)建分區(qū))
3)切割p_max分區(qū)為新分區(qū)和新的p_max分區(qū)(此處會(huì)調(diào)整p_max分區(qū)的分片策略)
七、批量維護(hù):批量添加表分區(qū)
批量給相關(guān)表添加表分區(qū),具體腳本如下:
CREATE DEFINER=`root`@`%` PROCEDURE `tables_add_monthly_partition`(IN tbl_prefix VARCHAR(64), IN year_no INT, IN month_no INT,OUT out_status INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl_name VARCHAR(64);
DECLARE cur CURSOR FOR
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE CONCAT(tbl_prefix, '%');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 輸出狀態(tài),開始執(zhí)行狀態(tài) 100,執(zhí)行成功狀態(tài) 200,執(zhí)行失敗狀態(tài) 50
SET out_status = 100;
-- 打開游標(biāo)
OPEN cur;
read_loop: LOOP
FETCH cur INTO tbl_name;
IF done THEN
LEAVE read_loop;
END IF;
-- 檢查表是否已經(jīng)是分區(qū)表
SET @is_partitioned = EXISTS (SELECT 1 FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = tbl_name);
IF NOT @is_partitioned THEN
-- 如果表不是分區(qū)表,先調(diào)用 convert_table_to_partition 進(jìn)行轉(zhuǎn)換
CALL convert_table_to_partition(tbl_name,@status);
-- 轉(zhuǎn)換后再次檢查是否成功轉(zhuǎn)換為分區(qū)表
SET @is_partitioned = EXISTS (SELECT 1 FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = tbl_name);
IF NOT @is_partitioned THEN
-- 如果轉(zhuǎn)換失敗,跳過后續(xù)操作并輸出錯(cuò)誤信息
SELECT CONCAT('Failed to convert table ', tbl_name, ' to partitioned. Skipping.') AS message;
SET out_status = 50;
ITERATE read_loop;
END IF;
END IF;
-- 調(diào)用 add_monthly_partitions 為當(dāng)前表添加分區(qū)
CALL add_monthly_partitions(tbl_name, year_no, month_no,@status);
-- 可選:輸出操作結(jié)果(用于調(diào)試)
-- SELECT CONCAT('Processed table: ', tbl_name) AS status;
END LOOP;
-- 關(guān)閉游標(biāo)
CLOSE cur;
-- 輸出完成信息
-- SELECT CONCAT('Batch partition addition completed for tables with prefix "', tbl_prefix, '".') AS message;
SET out_status = 200;
END批量添加表分區(qū)需要傳入相關(guān)表前綴,如上面示例中的“ai_result_”,此腳本會(huì)將非分區(qū)表轉(zhuǎn)換為分區(qū)表,再給分區(qū)表添加相應(yīng)的表分區(qū),具體執(zhí)行過程如下:
1)獲取所有相關(guān)表
2)遍歷判斷表是否是分區(qū)表
3)非分區(qū)表被轉(zhuǎn)換為分區(qū)表
4)給分區(qū)表添加表分區(qū)策略
該腳本請(qǐng)慎重執(zhí)行,上面我們有常規(guī)表和分區(qū)表的對(duì)比,執(zhí)行腳本很簡(jiǎn)單(批量自動(dòng)完成),但執(zhí)行的后果請(qǐng)慎重考慮!
總結(jié)
到此這篇關(guān)于MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)批量表分區(qū)的文章就介紹到這了,更多相關(guān)MySQL批量表分區(qū)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
安裝MySQL 5后無(wú)法啟動(dòng)(不能Start service)解決方法小結(jié)
有時(shí)候我們?cè)诎惭bmysql軟件時(shí),卻無(wú)法啟動(dòng),或服務(wù)器安全設(shè)置以后都可能導(dǎo)致mysql無(wú)法運(yùn)行2012-07-07
MySQL 中處理 BLOB 和 CLOB 數(shù)據(jù)類型小結(jié)
在MySQL中,BLOB和CLOB 數(shù)據(jù)類型用于存儲(chǔ)大量的二進(jìn)制數(shù)據(jù)和字符數(shù)據(jù),可以使用SQL 語(yǔ)句或編程語(yǔ)言將二進(jìn)制數(shù)據(jù)和字符數(shù)據(jù)插入到BLOB 和CLOB列中,這篇文章主要介紹了MySQL 中處理 BLOB 和 CLOB 數(shù)據(jù)類型,需要的朋友可以參考下2025-03-03
MYSQL統(tǒng)計(jì)總條數(shù)(需去重)使用的辦法總結(jié)
在數(shù)據(jù)庫(kù)操作中,經(jīng)常需要處理重復(fù)數(shù)據(jù)的問題,尤其是在進(jìn)行數(shù)據(jù)匯總或統(tǒng)計(jì)時(shí),這篇文章主要介紹了MYSQL統(tǒng)計(jì)總條數(shù)(需去重)使用的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-11-11
MySQL對(duì)小數(shù)進(jìn)行四舍五入的操作實(shí)現(xiàn)
數(shù)學(xué)函數(shù)是MySQL中常用的一類函數(shù),其主要用于處理數(shù)字,包括整型和浮點(diǎn)數(shù)等等,本文主要介紹了MySQL對(duì)小數(shù)進(jìn)行四舍五入的操作實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
SQL結(jié)果如何根據(jù)某個(gè)字段取最新時(shí)間去重
在日常的項(xiàng)目開發(fā)當(dāng)中,經(jīng)常會(huì)遇到獲取同一屬性相同的記錄,如何獲取記錄時(shí)間最新的那一條,下面這篇文章主要給大家介紹了關(guān)于SQL結(jié)果如何根據(jù)某個(gè)字段取最新時(shí)間去重的相關(guān)資料,需要的朋友可以參考下2023-06-06

