經常去重復數據,數據需要轉等操作,匯總高級SQL MySQL操作
?
一、數據去重(Data Deduplication)
?
去重常用于清除重復記錄,保留唯一數據。
?
1.?使用DISTINCT關鍵字去重單列
?
-- 從用戶表中獲取唯一的郵箱地址
SELECT DISTINCT email FROM users;
?
?
2.?使用GROUP BY結合聚合函數去重多列
?
-- 按姓名和手機號去重,獲取最新注冊的用戶
SELECT name, phone, MAX(register_time) AS latest_time
FROM users
GROUP BY name, phone;
?
?
3.?使用CTE和ROW_NUMBER()窗口函數標記重復行并刪除
?
-- 先標記重復行,再刪除非首行記錄
WITH DuplicateRows AS (
? ? SELECT id, name, email,
? ? ? ? ? ?ROW_NUMBER() OVER(PARTITION BY email ORDER BY id) AS row_num
? ? FROM users
)
DELETE FROM DuplicateRows WHERE row_num > 1;
?
?
二、數據行轉列(Pivot Table)
?
將行數據轉換為列,常用于統計匯總場景。
?
1.?使用CASE WHEN手動實現行轉列
?
-- 統計每個用戶的不同訂單類型數量
SELECT user_id,
? ? ? ?SUM(CASE WHEN order_type = '食品' THEN 1 ELSE 0 END) AS food_orders,
? ? ? ?SUM(CASE WHEN order_type = '服裝' THEN 1 ELSE 0 END) AS clothes_orders,
? ? ? ?SUM(CASE WHEN order_type = '數碼' THEN 1 ELSE 0 END) AS digital_orders
FROM orders
GROUP BY user_id;
?
?
2.?使用IF函數結合GROUP BY實現動態列
?
-- 按月份統計銷售額(假設月份存于month列)
SELECT product_id,
? ? ? ?SUM(IF(month = 1, sales_amount, 0)) AS jan_sales,
? ? ? ?SUM(IF(month = 2, sales_amount, 0)) AS feb_sales,
? ? ? ?SUM(IF(month = 3, sales_amount, 0)) AS mar_sales
FROM sales
GROUP BY product_id;
?
?
3.?使用動態SQL生成行轉列語句(適用于列名不確定的場景)
?
-- 動態生成SQL(需先查詢列名)
SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT?
? ? ? ?CONCAT('SUM(CASE WHEN category = ''', category, ''' THEN amount ELSE 0 END) AS `', category, '`')
) INTO @sql
FROM sales_data;
?
SET @sql = CONCAT('SELECT year, ', @sql, ' FROM sales_data GROUP BY year');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
?
?
三、數據類型轉換(Data Type Conversion)
?
在MySQL中轉換數據類型,需注意兼容性和精度損失。
?
1.?顯式轉換:使用CAST()函數
?
-- 將字符串轉為日期類型
SELECT CAST('2025-06-20' AS DATE) AS date_value;
?
-- 將數字轉為字符串(常用于拼接)
SELECT CONCAT('訂單金額:', CAST(amount AS CHAR)) AS order_info
FROM orders;
?
?
2.?顯式轉換:使用CONVERT()函數
?
-- 將字符串轉為DECIMAL類型(保留2位小數)
SELECT CONVERT('123.45', DECIMAL(10,2)) AS price;
?
-- 將日期轉為UNIX時間戳
SELECT CONVERT('2025-06-20', UNSIGNED) AS timestamp_value;
?
?
3.?隱式轉換(MySQL自動轉換,但需注意風險)
?
-- 字符串自動轉數字(僅當字符串為純數字時有效)
SELECT '123' + 456; -- 結果:579
?
-- 日期字符串自動轉日期類型(需符合格式)
INSERT INTO dates (date_col) VALUES ('2025-06-20');
?
?
注意事項
?
- 數據去重:使用?DISTINCT?時會對所有列去重,性能低于?GROUP BY?;刪除重復行前建議先備份數據。
- 行轉列:手動編寫CASE WHEN適用于列數固定的場景,動態SQL需注意SQL注入風險。
- 類型轉換:隱式轉換可能導致意外錯誤(如?'abc' + 1?會轉為?0 + 1?),建議優先使用顯式轉換。