この記事は、主に説明します
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
;