維表是一張不斷變化的表(不更新的表是變化表的一種特例)。
如何查詢或JOIN一張不斷變化的表? 如果用傳統的JOIN文法來表達
JOIN dim_table ON xxx
,會導緻多次運作得到的結果不一緻。是以在查詢或JOIN維表的時候,需要明确指名要檢視的是維表的哪個時刻的快照。是以,需要引入 SQL:2011 的Temporal Table語義。
維表DDL
Flink SQL中沒有專門為維表設計的DDL文法,使用标準的
CREATE TABLE文法即可,同時需額外增加一行
PERIOD FOR SYSTEM_TIME
的聲明。這行聲明定義了維表的變化周期,即表明該表是一張會變化的表。
維表DDL示例
-
CREATE TABLE white_list (
-
id varchar,
-
name varchar,
-
age int,
-
PRIMARY KEY (id), -- 用作維表的話,必須有聲明的主鍵
-
PERIOD FOR SYSTEM_TIME
-
) with (
-
type = 'xxx',
-
...
-
)
維表具體聲明方式和參數請參見
維表建立。
注意:聲明一個維表時,必須指明主鍵。維表JOIN時,ON的條件必須包含所有主鍵的等值條件。
維表JOIN
維表是一張不斷變化的表,是以在JOIN維表的時候,需指明這條記錄關聯維表哪個時刻的快照。目前僅支援關聯目前時刻的維表(未來會支援關聯左表rowtime所對應的維表快照)。
維表JOIN文法
-
SELECT column-names
-
FROM table1 [AS <alias1>]
-
[LEFT] JOIN table2 FOR SYSTEM_TIME AS OF PROCTIME() [AS <alias2>]
-
ON table1.column-name1 = table2.key-name1
- 維表支援
和INNER JOIN
,不支援LEFT JOIN
或RIGHT JOIN
FULL JOIN
- JOIN維表時,在維表後必須加上
FOR SYSTEM_TIME AS OF PROCTIME()
說明:
含義是:JOIN維表目前時刻所看到的每條資料。FOR SYSTEM_TIME AS OF PROCTIME()
- 維表JOIN工作模式是左表的一條記錄到達時,在維表中查詢并關聯上比對的資料。如果維表插入了一條資料能比對上之前左表的資料時,JOIN的結果流不會發出更新的資料以彌補之前的未比對。
- JOIN行為隻發生在處理時間(processing time),即使維表中的資料都被删了,之前JOIN流已經發出的關聯上的資料也不會被撤回或改變。
例如,事件流JOIN白名單維表的SQL如下。
-
SELECT e.*, w.*
-
FROM event AS e
-
JOIN white_list FOR SYSTEM_TIME AS OF PROCTIME() AS w
-
ON e.id = w.id
注意:
- 維表JOIN的ON條件中一定要有包括維表primary key的等值條件,因為需要根據key來查維表。ON條件中可以有其他條件,例如
,其他條件需要包含所有維表主鍵的等值條件。
ON event.id = white_list.id AND event.name = white_list.name
- 維表和維表不能做JOIN。DDL聲明的字段、主鍵等需要和真實表裡面定義的一緻。
維表示例
測試資料
nameinfo:
id(bigint) | name(VARCHAR) | age(bigint) |
---|---|---|
1 | lilei | 22 |
2 | hanmeimei | 20 |
3 | libai | 28 |
phoneNumber:
phoneNumber(bigint) | |
---|---|
dufu | 18867889855 |
baijuyi | 18867889856 |
18867889857 | |
18867889858 |
測試語句
-
CREATE TABLE datahub_input1 (
-
id BIGINT,
-
name VARCHAR,
-
age BIGINT
-
) WITH (
-
type='datahub'
-
);
-
create table phoneNumber(
-
name VARCHAR,
-
phoneNumber bigint,
-
primary key(name),
-
PERIOD FOR SYSTEM_TIME
-
)with(
-
type='rds'
-
);
-
CREATE table result_infor(
-
id bigint,
-
phoneNumber bigint,
-
name VARCHAR
-
)with(
-
type='rds'
-
);
-
INSERT INTO result_infor
-
SELECT
-
t.id
-
,w.phoneNumber
-
,t.name
-
FROM datahub_input1 as t
-
JOIN phoneNumber FOR SYSTEM_TIME AS OF PROCTIME() as w
-
ON t.name = w.name;
測試結果
name(varchar) | ||
---|---|---|
本文轉自實時計算——
維表JOIN語句