MySQL 8 データ クリーニングの 3 つの要素:
- ライブラリテーブルのコピーとデータのバックアップ
- データクリーニングSQL
- データ クリーニング ニルヴァーナ - ストアド プロシージャ
前提条件: データベース関連付けテーブルの初期化と基本データの初期化:
-- usc.t_project definition
CREATE TABLE `t_project` (
`id` varchar(64) NOT NULL COMMENT '主键',
`tid` varchar(64) NOT NULL COMMENT 'TID',
`ptid` varchar(64) NOT NULL COMMENT 'PTID',
`project_no` varchar(64) DEFAULT NULL COMMENT '项目编号',
`project_name` varchar(128) NOT NULL COMMENT '项目名称',
`project_address` varchar(128) NOT NULL COMMENT '项目地址',
`is_delete` int NOT NULL DEFAULT '0' COMMENT '删除标识:0=未删除,1=已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `t_project_id_IDX` (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- usc.t_arch definition
CREATE TABLE `t_arch` (
`tid` varchar(64) NOT NULL COMMENT 'TID',
`ptid` varchar(64) NOT NULL COMMENT 'PTID',
`id` varchar(64) NOT NULL COMMENT '主键',
`project_id` varchar(64) NOT NULL COMMENT '项目ID',
`project_no` varchar(100) NOT NULL COMMENT '项目编号',
`arch_name` varchar(128) NOT NULL COMMENT '案卷名称',
`arch_no` varchar(128) NOT NULL COMMENT '案卷编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
上記のデータベース テーブル間の関係: 1:N = プロジェクト:ケース ファイル
-- 项目基础数据
INSERT INTO usc.t_project (id,tid,ptid,project_no,project_name,project_address,is_delete) VALUES
('1','430100','430000','1001','长沙国金中心','长沙市芙蓉区', 0),
('2','430100','430000','1001','长沙国金中心','长沙市芙蓉区', 0);
-- 案卷基础数据
INSERT INTO usc.t_arch (tid,ptid,id,project_id,project_no,arch_name,arch_no) VALUES
('430100','430000','1','1','1001','案卷一','案卷一'),
('430100','430000','2','2','1002','案卷二','案卷二'),
('430100','430000','3','2','1002','案卷三','案卷三');
ライブラリテーブルのコピーとデータのバックアップ
MySQL 8 クライアントで次のコマンドを実行します。
-- 复制t_project 表结构
create table t_project_2023_08_29 like t_project;
-- 拷贝t_project 表的数据至t_project_2023_08_29
insert into t_project_2023_08_29 select * from t_project
-- t_arch 执行如下命令, 注意替换相关表名
create table t_arch_2023_08_29 like t_arch ;
insert into t_arch_2023_08_29 select * from t_arch
データクリーニングSQL
データクリーニングの 5 つの要素:
- データクリーニングのフィルター条件を決定する
- データクリーニングのためのデータレコードを決定する
- データクリーニングのフィルター条件を決定する
- データ クリーニングの更新フィールドを決定する
- データクリーニング後の検証
実践的な戦闘: 昨夜、私は友人が ****** Urban Construction Archives の履歴データを移行するためのシェル スクリプトを書くのを手伝いました。本日、移行された過去のプロジェクト情報が重複しており、その結果、プロジェクトに関連するケースファイルが欠落しているというフィードバックを受けました。
データ クリーニングの 5 つの要素に従って、プロジェクト関連のケース ファイルのクリーニング SQL を記述する方法を段階的に確認します。
1. データ クリーニングのフィルタリング条件を決定します。
select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1
この SQL 関数の意味: プロジェクト テーブルの Tid\Ptid\Project_no フィールドによってグループ化されたプロジェクト情報をクエリし、その数値が 1 より大きい。
上のスクリーンショットは、プロジェクト テーブルに重複したレコードがあることを示しています。
2. データ クリーニングの対象となるデータ レコードを決定します。
select * from t_arch ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
on ta.tid = temp.tid and ta.ptid = temp.ptid and ta.project_no = temp.project_no
この SQL 関数の意味: インライン モードを使用して、ケース ファイル テーブルとプロジェクト テーブルをクエリします [条件追加: データ クリーニングのフィルター条件]。
上のスクリーンショットは、クリーンアップする必要があるケース ファイル テーブル内のレコードの数を示しています。
3. データクリーニングのフィルタ条件を決定する
一般に、フィルター条件は、クエリ レコード フィールドと関連テーブルの関連フィールドです。
select * from t_arch ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
on ta.tid = temp.tid and ta.ptid = temp.ptid and ta.project_no = temp.project_no
where ta.project_id in (
select tp.id from t_project tp where tp.tid = temp.tid and tp.ptid = temp.ptid and tp.project_no = temp.project_no
)
この SQL 関数の意味: クエリ フィールド temp.tid\temp.ptid\temp.project_no を使用してスレーブ テーブル t_project を関連付け、マスター テーブル t_arch の関連付けを満たす project_id をクエリします。
上のスクリーンショットは、ケース ファイル テーブル内でクリーニングする必要があるレコードの数と、フィルタリングに関連する条件が追加されていることを示しています。
4. データ クリーニングの更新フィールドを決定します。
ケースファイルテーブルの project_id フィールドを更新する必要があり、Select ステートメントを Update ステートメントに変更する必要があります。
update t_arch ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
on ta.tid = temp.tid and ta.ptid = temp.ptid and ta.project_no = temp.project_no
set ta.project_id = (select min(tp.id) from t_project tp where tp.tid = temp.tid and tp.temp.ptid and tp.project_no = temp.project_no group by tp.tid, tp.ptid, tp.project_no limit 1)
where ta.project_id in (
select tp.id from t_project tp where tp.tid = temp.tid and tp.ptid = temp.ptid and tp.project_no = temp.project_no
)
キー ポイント: スレーブ テーブルに重複があります。通常は、min/max 関数 + グループ化 +limit + マスター テーブルの関連フィールドのフィルターを使用し、Set の条件を満たすスレーブ テーブルのフィールドをクエリすることをお勧めします。
(select min(tp.id) from t_project tp where tp.tid = temp.tid and tp.temp.ptid and tp.project_no = temp.project_no group by tp.tid, tp.ptid, tp.project_no limit 1)
5. データクリーニング後の検証
select * from t_arch ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
この SQL 関数の意味: データのクリーニング記録を確認します。
上記のスクリーンショットの識別: データ クリーニングとフィルタリング レコードのスクリーンショットでは、project_id フィールドが 1 に置き換えられていることが明らかにわかりましたが、データ検証のクリーニング レコード SQL は引き続き関連データをクエリできますが、project_id フィールドは管理されています。 t_project テーブルのデータはクリーンアップされていないため、t_arch テーブルによるデータは正しいです。
データクリーニングの拡張
次の SQL には主に T_Project テーブル データのクリーニングが含まれます
update t_project ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
on ta.tid = temp.tid and ta.ptid = temp.ptid and ta.project_no = temp.project_no
set ta.is_delete = 1
where ta.id not in (
select min_id from (select min(tp.id) as min_id from t_project tp where tp.is_delete = 0 group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
)
キーポイント: メインテーブルはメインテーブルをカスケードし、フィルター条件に基づいて一時テーブルを構築します。メインテーブル内の重複レコードをフィルターするための Where 条件を追加し、is_delete = 1 を設定します。
親切なヒント:
メインテーブルのデータクリーニングの条件は次のとおりです。 メインテーブルの重複レコード条件
ビジネステーブルカスケードメインテーブルのデータクリーニング条件は以下のとおりです。 条件を満たすレコードのフィールド条件を問い合わせる
メインテーブルのデータクリーニング SQL:
update t_project ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
on ta.tid = temp.tid and ta.ptid = temp.ptid and ta.project_no = temp.project_no
set ta.is_delete = 1
where ta.id not in (
select min_id from (select min(tp.id) as min_id from t_project tp where tp.is_delete = 0 group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
)
テーブルカスケードマスターテーブルデータから SQL をクリーンアップします。
update t_arch ta
inner join (select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1) temp
on ta.tid = temp.tid and ta.ptid = temp.ptid and ta.project_no = temp.project_no
set ta.project_id = (select min(tp.id) from t_project tp where tp.tid = temp.tid and tp.temp.ptid and tp.project_no = temp.project_no group by tp.tid, tp.ptid, tp.project_no limit 1)
where ta.project_id in (
select tp.id from t_project tp where tp.tid = temp.tid and tp.ptid = temp.ptid and tp.project_no = temp.project_no
)
データ クリーニング ニルヴァーナ - ストアド プロシージャ
データ クリーニング SQL がデータ クリーニングの期待に応えられない場合は、ストアド プロシージャを使用してデータ クリーニング機能を実装します。
前提条件:
- MySQL 8 ストアド プロシージャの基本構文に精通し、理解しておいてください。
- ストアド プロシージャでの変数の宣言と代入に精通している。
- ストアド プロシージャでのカーソル宣言とトラバースに関する知識。
- ストアド プロシージャの IF...ELSE 判定に精通している
- ストアド プロシージャの演算子についてよく理解してください。
MySQL 8 ストアド プロシージャを初めて使用する場合は、「MySQL 8 ストアド プロシージャを理解するための 1 つの記事」を参照することをお勧めします。
プロジェクトとファイルのクリーニング ストアド プロシージャのソース コード:
delimiter $
create procedure distanct_project()
begin
-- 变量声明
declare tid varchar(64);
declare ptid varchar(64);
declare project_no varchar(64);
declare min_id varchar(64);
-- 定义游标遍历标识符
declare done int default 0;
-- 游标定时
declare project_cursor cursor for select tp.tid, tp.ptid, tp.project_no from t_project tp group by tp.tid, tp.ptid, tp.project_no having(count(1)) > 1;
-- 游标全部遍历完成时,将游标遍历标识符设置为1
declare continue handler for not found set done =1;
-- 打开游标
open project_cursor;
-- 游标遍历
read_project:LOOP
-- 从游标中获取下一行数据
FETCH project_cursor INTO tid, ptid, project_no;
-- 判断是否已经遍历完所有行
IF done THEN
LEAVE read_project;
END IF;
-- 查询
select min(tp.id) into min_id from t_project tp where tp.tid = tid and tp.ptid = ptid and tp.project_no = project_no group by tp.tid, tp.ptid, tp.project_no limit 1;
-- 从表更新
update t_arch ta set ta.project_id = min_id where ta.tid =tid and ta.ptid =ptid and ta.project_no =project_no;
-- 主表更新
update t_project tp
set tp.is_delete = 1
where tp.tid =tid and tp.ptid = ptid and tp.project_no = project_no and tp.id <> min_id;
END LOOP;
-- 关闭游标
CLOSE project_cursor;
end $
call distanct_project ();
注意: 複雑なビジネス データ クリーニングの場合、たとえば、商業住宅管理システム: プロジェクト - 「建物 -」 住宅 - 「オンライン契約署名 -」 販売前証明書やその他の多レベルおよび多次元のデータ クリーニングは、何も行いません。カーソルを Cursor に入れ子にしてから、選択クエリと挿入を実行し、最後に IF...ELSE を実行して挿入/更新ステートメントを判断して実行します。
今日の分析はここで終わります。