データウェアハウス_ジッパーテーブル_ジッパーテーブル実装のアイデア

この記事は、主に説明します

 1.ジッパーテーブルとジッパーの表示例とは

 2.異なるオリジナルテーブルの下にジッパーテーブルを作成する方法

 

まずはジッパーテーブルとは

 

1.ジッパーテーブルとジッパーの表示例とは

ジッパー時計とは

     ディメンションデータが変更されると、古いデータは無効になり、変更されたデータは新しいレコードとしてディメンションテーブルに挿入されて有効になります。これにより、特定の粒度でデータ変更の履歴を記録できます。

 

 

ジッパーテーブルの例

      私の他の記事を見てください

 https://blog.csdn.net/u010003835/article/details/104420723

 

 

 

 2.異なるオリジナルテーブルの下にジッパーテーブルを作成する方法

 

1.最初のケース、標準化されたテーブル

    標準テーブルとは何ですか?標準とは、元のテーブルにcreate_time、update_timeが含まれていることを意味します  

 

元のテーブルをデータウェアハウステーブルにすると、毎日の収集方法

次に、テーブルを作成し、テストデータを挿入します


use data_warehouse_test;

CREATE TABLE IF NOT EXISTS user_zipper_org (
	user_id BIGINT COMMENT '用户id'
	,user_name STRING COMMENT '用户姓名'
	,create_time DATE COMMENT '创建时间'
	,update_time DATE COMMENT '修改时间'
) 
PARTITIONED BY(
	pt STRING COMMENT '数据分区'
)
STORED AS ORC
;


ALTER TABLE user_zipper_org DROP IF EXISTS PARTITION (pt = '20200320');
ALTER TABLE user_zipper_org DROP IF EXISTS PARTITION (pt = '20200321');


INSERT INTO TABLE user_zipper_org PARTITION (pt = '20200320')
VALUES 
(1, 'szh', '2020-01-01', '2020-01-01')
,(2, 'yuqin', '2020-01-01', '2020-01-01')
,(3, 'heping', '2020-01-01', '2020-01-01')
,(4, 'quxingma', '2020-01-01', '2020-01-01')
,(5, 'zhouzhou', '2020-01-01', '2020-01-01')
;

INSERT INTO TABLE user_zipper_org PARTITION (pt = '20200321')
VALUES 
(1, 'szh2', '2020-01-01', '2020-03-21')
,(2, 'yuqin', '2020-01-01', '2020-01-01')
,(3, 'heping3', '2020-01-01', '2020-03-21')
,(4, 'quxingma', '2020-01-01', '2020-01-01')
,(5, 'zhouzhou', '2020-01-01', '2020-01-01')
,(6, 'newuser', '2020-03-21', '2020-03-21')
;

 

最終的なジッパーテーブルを作成します。データのセキュリティを確保するために、最終的なジッパーテーブルはパーティションテーブルです。

まず、ジッパーテーブルは20200320から作成されているため、元のテーブルのデータはすべて現在有効なデータと同等であり、これらのデータに基づいて最終的な20200320のジッパーテーブルデータを作成します。

次に、ファイナルテーブル20200320でパーティション分割されたデータから一時テーブルを作成する必要があります。

上記の2つのステップのSQLは次のとおりです。

use data_warehouse_test;

CREATE TABLE IF NOT EXISTS user_zipper_final
(
	user_id BIGINT COMMENT '用户id'
	,user_name STRING COMMENT '用户姓名'
	,create_time DATE COMMENT '创建时间'
	,update_time DATE COMMENT '修改时间'
	,start_date DATE COMMENT '生效时间'
	,end_date DATE COMMENT '失效时间'
)
PARTITIONED BY(
	pt STRING COMMENT '数据分区'
);


INSERT OVERWRITE TABLE user_zipper_final PARTITION (pt = '20200320')
SELECT 
	org.user_id
	,org.user_name
	,org.create_time
	,org.update_time
	,'2020-03-20' AS start_date
	,'9999-12-31' AS end_date
FROM user_zipper_org AS org
WHERE pt = '20200320'
;


DROP TABLE IF EXISTS tmp_user_zipper_mid;
CREATE TABLE tmp_user_zipper_mid AS
SELECT 
	org.user_id
	,org.user_name
	,org.create_time
	,org.update_time
	,org.start_date
	,org.end_date
FROM user_zipper_final AS org
WHERE pt = '20200320'
;

 

 

主要なステップは、20200321で変更されたデータに基づいています(新規および変更)

新しいcreate_timeは2020-03-21です

変更されたupdate_timeは2020-03-21です。

そして、20200320のジッパーテーブルデータを構築するための、20200320のジッパーテーブルデータの全量(ここでは、最初に一時テーブル、つまり中間テーブルとして保存します)

 

まず、この方法で新しいデータと変更されたデータを取得できます

2020-03-21 发生变动的数据

SELECT 
	org.user_id
	,org.user_name
	,org.create_time
	,org.update_time
	,'2020-03-20' AS start_date
	,'9999-12-31' AS end_date
FROM user_zipper_org AS org
WHERE pt = '20200321'
	AND (
		(
			create_time = '2020-03-21'
		)
		OR
		(
			update_time = '2020-03-21'
		)
	)
;

 

20200321のフルジッパーテーブルのデータは、次の方法で作成できます。

use data_warehouse_test;

DROP TABLE IF EXISTS tmp_user_zipper_mid;

CREATE TABLE tmp_user_zipper_mid AS
SELECT *
FROM
(
SELECT 
	final.user_id
	,final.user_name
	,final.create_time
	,final.update_time
	,final.start_date
	,CAST (
		(
			CASE 
				WHEN 
					(
						new_data.user_id IS NOT NULL 
						AND
						final.end_date >= '2020-03-21' 
					)
					THEN '2020-03-20'
				ELSE final.end_date
			END 
		)	
		AS DATE
	)
	AS end_date
FROM 
	user_zipper_final AS final
LEFT JOIN (
	SELECT 
	org.user_id
	,org.user_name
	,org.create_time
	,org.update_time
	FROM user_zipper_org AS org
	WHERE pt = '20200321'
		AND (
			(
				create_time = '2020-03-21'
			)
			OR
			(
				update_time = '2020-03-21'
			)
		)
) AS new_data
ON  new_data.user_id = final.user_id
WHERE final.pt = '20200320'

UNION ALL

SELECT 
	new_data.user_id
	,new_data.user_name
	,new_data.create_time
	,new_data.update_time
	,CAST( '2020-03-21' AS DATE ) AS start_date
	,CAST ('9999-12-31' AS DATE ) AS end_date
FROM (
	SELECT 
	org.user_id
	,org.user_name
	,org.create_time
	,org.update_time
	FROM user_zipper_org AS org
	WHERE pt = '20200321'
		AND (
			(
				create_time = '2020-03-21'
			)
			OR
			(
				update_time = '2020-03-21'
			)
		)
) AS new_data
) AS tmp
;

 

 

最後に、一時テーブルの結果を新しいジッパーテーブルパーティションに挿入します。

次に、データ(

1.最新のジッパーテーブルパーティションデータを取得する

2.ジッパーテーブルから2020-03-20のデータを取得します

3.ジッパーテーブルから2020-03-21のデータを取得します


use data_warehouse_test;

INSERT OVERWRITE TABLE user_zipper_final PARTITION (pt = '20200321')
SELECT 
	* 
FROM tmp_user_zipper_mid
;


SELECT *
FROM user_zipper_final
WHERE pt = '20200321'
;


SELECT * 
FROM user_zipper_final 
WHERE pt = '20200321' 
	AND start_date <= '2020-03-20' 
	AND end_date >= '2020-03-20'
;


SELECT * 
FROM user_zipper_final 
WHERE pt = '20200321' 
	AND start_date <= '2020-03-21' 
	AND end_date >= '2020-03-21'
;

 

 

 

2. 2番目のケース、非標準の元のテーブル

     非標準の元のテーブルとは、元のテーブルにcreate_timeまたはupdate_timeがないことです。あるいは、この2つは存在しません。このような状況で、ジッパーテーブルをどのように構築すればよいでしょうか。

 

私たちはこの問題を注意深く分析し、それをどのように解決しますか?

まず、単一のcreate_timeまたはupdate_timeでは変更されたデータを区別できないことがわかります。

したがって、私たちのアイデアは、変更されたデータを識別する列を作成することです。

すべての列でmd5値を取る方法を選択します!

 

元のテーブルに次の列があるとします。

user_id、user_name、create_time

则MD5(CONCAT(user_id、user_name、create_time))  

初期ジッパーテーブルが既にあると仮定すると、変更されたデータ(新規および変更)を取得する方法に問題があります。

変更されたデータを取得するためのSQLは次のとおりです。

SELECT
	ta.*
FROM 
(
	SELECT 
		user_id
		,user_name
		,create_time
		,MD5(CONCAT(user_id,user_name,create_time)) AS user_flag
	FROM user_zipper_org
	WHERE pt = '20200321'
) AS ta
LEFT JOIN (
	SELECT 
		user_id
		,user_flag
	FROM user_zipper_final
	WHERE pt = '20200320'
		AND start_date <= '2020-03-20'
		AND end_date >= '2020-03-20'
) AS tb
ON ta.user_id = tb.user_id
AND ta.user_flag != tb.user_flag
;

 

 

 

 

 

 

元の記事を519件公開 1146 件を賞賛 283万回の閲覧

おすすめ

転載: blog.csdn.net/u010003835/article/details/104849019