--********************************************************************-- -- Flink SQL 快速入门示例 创建表 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- -- 执行创建临时表 DDL,不需要指定catalog.database CREATE TABLE orders ( order_uid BIGINT, product_id BIGINT, price DECIMAL(32, 2), order_time TIMESTAMP(3) ) WITH ( 'connector' = 'datagen' ); --********************************************************************-- -- Flink SQL 快速入门示例 INSERT INTO --********************************************************************-- -- 定义数据源表 CREATE TABLE server_logs ( client_ip STRING, client_identity STRING, userid STRING, user_agent STRING, log_time TIMESTAMP(3), request_line STRING, status_code STRING, size INT ) WITH ( 'connector' = 'faker', 'fields.client_ip.expression' = '#{Internet.publicIpV4Address}', 'fields.client_identity.expression' = '-', 'fields.userid.expression' = '-', 'fields.user_agent.expression' = '#{Internet.userAgentAny}', 'fields.log_time.expression' = '#{date.past ''15'',''5'',''SECONDS''}', 'fields.request_line.expression' = '#{regexify ''(GET|POST|PUT|PATCH){1}''} #{regexify ''(/search\.html|/login\.html|/prod\.html|cart\.html|/order\.html){1}''} #{regexify ''(HTTP/1\.1|HTTP/2|/HTTP/1\.0){1}''}', 'fields.status_code.expression' = '#{regexify ''(200|201|204|400|401|403|301){1}''}', 'fields.size.expression' = '#{number.numberBetween ''100'',''10000000''}' ); -- 定义结果表,实际应用中会选择 Kafka、JDBC 等作为结果表 CREATE TABLE client_errors ( log_time TIMESTAMP(3), request_line STRING, status_code STRING, size INT ) WITH ( 'connector' = 'stream-x' ); -- 写入数据到结果表 INSERT INTO client_errors SELECT log_time, request_line, status_code, size FROM server_logs WHERE status_code SIMILAR TO '4[0-9][0-9]'; --********************************************************************-- -- Flink SQL 快速入门示例 Statement Set --********************************************************************-- -- 定义数据源表 CREATE TABLE server_logs ( client_ip STRING, client_identity STRING, userid STRING, user_agent STRING, log_time TIMESTAMP(3), request_line STRING, status_code STRING, size INT, WATERMARK FOR log_time AS log_time - INTERVAL '30' SECONDS ) WITH ( 'connector' = 'faker', -- Faker 连接器仅在 VVR-4.0.12 及以上支持 'fields.client_ip.expression' = '#{Internet.publicIpV4Address}', 'fields.client_identity.expression' = '-', 'fields.userid.expression' = '-', 'fields.user_agent.expression' = '#{Internet.userAgentAny}', 'fields.log_time.expression' = '#{date.past ''15'',''5'',''SECONDS''}', 'fields.request_line.expression' = '#{regexify ''(GET|POST|PUT|PATCH){1}''} #{regexify ''(/search\.html|/login\.html|/prod\.html|cart\.html|/order\.html){1}''} #{regexify ''(HTTP/1\.1|HTTP/2|/HTTP/1\.0){1}''}', 'fields.status_code.expression' = '#{regexify ''(200|201|204|400|401|403|301){1}''}', 'fields.size.expression' = '#{number.numberBetween ''100'',''10000000''}' ); -- 定义结果表1 CREATE TABLE aggregations1 ( `browser` STRING, `status_code` STRING, `end_time` TIMESTAMP(3), `requests` BIGINT NOT NULL ) WITH ( 'connector' = 'blackhole' ); -- 定义结果表2 CREATE TABLE aggregations2 ( `browser` STRING, `status_code` STRING, `requests` BIGINT NOT NULL ) WITH ( 'connector' = 'stream-x' ); -- This is a shared view that will be used by both insert into statements CREATE VIEW browsers AS SELECT REGEXP_EXTRACT(user_agent,'[^\/]+') AS browser, status_code, log_time FROM server_logs; -- 封装多个INSERT INTO语句到一个STATEMENT SET语句中 BEGIN STATEMENT SET; -- 5min窗口粒度聚合 INSERT INTO aggregations1 SELECT browser, status_code, TUMBLE_ROWTIME(log_time, INTERVAL '5' MINUTE) AS end_time, COUNT(*) requests FROM browsers GROUP BY browser, status_code, TUMBLE(log_time, INTERVAL '5' MINUTE); -- 1h窗口粒度聚合 INSERT INTO aggregations2 SELECT browser, status_code, COUNT(*) requests FROM browsers GROUP BY browser, status_code, TUMBLE(log_time, INTERVAL '1' HOUR); END; --********************************************************************-- -- Flink SQL 快速入门示例 Watermark -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.doctor_sightings ( doctor STRING, sighting_time TIMESTAMP(3), -- 通过watermark把sighting_time标识为事件时间,定义最大的乱序时间:期望所有的记录在目击发生后的15秒内都到达。 WATERMARK FOR sighting_time AS sighting_time - INTERVAL '15' SECONDS ) WITH ( 'connector' = 'faker', 'fields.doctor.expression' = '#{dr_who.the_doctors}', 'fields.sighting_time.expression' = '#{date.past ''15'',''SECONDS''}' ); SELECT doctor, -- 在滚动窗口中使用sighting_time字段 TUMBLE_ROWTIME(sighting_time, INTERVAL '1' MINUTE) AS sighting_time, COUNT(*) AS sightings FROM dt_catalog.dt_db.doctor_sightings GROUP BY TUMBLE(sighting_time, INTERVAL '1' MINUTE), doctor; --********************************************************************-- -- Flink SQL 快速入门示例 GROUP BY -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- -- 定义数据源表 CREATE TABLE dt_catalog.dt_db.server_logs ( client_ip STRING, client_identity STRING, userid STRING, user_agent STRING, log_time TIMESTAMP(3), request_line STRING, status_code STRING, size INT ) WITH ( 'connector' = 'faker', 'fields.client_ip.expression' = '#{Internet.publicIpV4Address}', 'fields.client_identity.expression' = '-', 'fields.userid.expression' = '-', 'fields.user_agent.expression' = '#{Internet.userAgentAny}', 'fields.log_time.expression' = '#{date.past ''15'',''5'',''SECONDS''}', 'fields.request_line.expression' = '#{regexify ''(GET|POST|PUT|PATCH){1}''} #{regexify ''(/search\.html|/login\.html|/prod\.html|cart\.html|/order\.html){1}''} #{regexify ''(HTTP/1\.1|HTTP/2|/HTTP/1\.0){1}''}', 'fields.status_code.expression' = '#{regexify ''(200|201|204|400|401|403|301){1}''}', 'fields.size.expression' = '#{number.numberBetween ''100'',''10000000''}' ); -- 采样user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A -- 正则表达式: '[^\/]+' (匹配 '/' 之前的所有字符) SELECT REGEXP_EXTRACT(user_agent,'[^\/]+') AS browser, status_code, COUNT(*) AS cnt_status FROM dt_catalog.dt_db.server_logs -- 按浏览器和状态码两个维度统计日志数量 GROUP BY REGEXP_EXTRACT(user_agent,'[^\/]+'), status_code; --********************************************************************-- -- Flink SQL 快速入门示例 滚动窗口聚合 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.server_logs ( client_ip STRING, client_identity STRING, userid STRING, request_line STRING, status_code STRING, log_time AS PROCTIME() -- 使用当前系统处理时间作为表的时间字段 ) WITH ( 'connector' = 'faker', 'fields.client_ip.expression' = '#{Internet.publicIpV4Address}', 'fields.client_identity.expression' = '-', 'fields.userid.expression' = '-', 'fields.log_time.expression' = '#{date.past ''15'',''5'',''SECONDS''}', 'fields.request_line.expression' = '#{regexify ''(GET|POST|PUT|PATCH){1}''} #{regexify ''(/search\.html|/login\.html|/prod\.html|cart\.html|/order\.html){1}''} #{regexify ''(HTTP/1\.1|HTTP/2|/HTTP/1\.0){1}''}', 'fields.status_code.expression' = '#{regexify ''(200|201|204|400|401|403|301){1}''}' ); -- 按 window_start, window_end 维度计算每分钟窗口上不同的 ip 数量 SELECT window_start, window_end, COUNT(DISTINCT client_ip) AS ip_addresses FROM TABLE( -- 定义1min滑动窗口 TUMBLE(TABLE dt_catalog.dt_db.server_logs, DESCRIPTOR(log_time), INTERVAL '1' MINUTE)) GROUP BY window_start, window_end; --********************************************************************-- -- Flink SQL 快速入门示例 滑动窗口聚合 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.bids ( bid_id STRING, currency_code STRING, bid_price DOUBLE, transaction_time TIMESTAMP(3), WATERMARK FOR transaction_time AS transaction_time - INTERVAL '5' SECONDS -- 定义事件时间,允许的最大窗口延迟为5s ) WITH ( 'connector' = 'faker', 'fields.bid_id.expression' = '#{Internet.UUID}', 'fields.currency_code.expression' = '#{regexify ''(EUR|USD|CNY)''}', 'fields.bid_price.expression' = '#{Number.randomDouble ''2'',''1'',''150''}', 'fields.transaction_time.expression' = '#{date.past ''30'',''SECONDS''}', 'rows-per-second' = '100' ); -- 定义1min 的滑动窗口,每隔 30s 滚动一次 SELECT window_start, window_end, currency_code, ROUND(AVG(bid_price),2) AS MovingAverageBidPrice FROM TABLE( HOP(TABLE dt_catalog.dt_db.bids, DESCRIPTOR(transaction_time), INTERVAL '30' SECONDS, INTERVAL '1' MINUTE)) GROUP BY window_start, window_end, currency_code; --********************************************************************-- -- Flink SQL 快速入门示例 累计窗口聚合 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- -- 商品销售订单表 CREATE TABLE dt_catalog.dt_db.orders ( order_id BIGINT, -- 订单ID goods_id BIGINT, -- 商品ID goods_sales DOUBLE, -- 商品销售额 order_time TIMESTAMP(3), -- 下单时间 WATERMARK FOR order_time AS order_time - INTERVAL '5' SECONDS -- 定义事件时间,允许的最大窗口延迟为5s ) WITH ( 'connector' = 'faker', 'fields.order_id.expression' = '#{number.numberBetween ''0'',''1000000000''}', 'fields.goods_id.expression' = '#{number.numberBetween ''0'',''1000000000''}', 'fields.goods_sales.expression' = '#{Number.randomDouble ''2'',''1'',''150''}', 'fields.order_time.expression' = '#{date.past ''30'',''SECONDS''}', 'rows-per-second' = '100' ); -- 每分钟更新一次从零点开始截止到当前时刻的累计销售额 SELECT window_start, window_end, SUM(goods_sales) AS cumulate_gmv -- 当天累计销售额 FROM TABLE( -- 定义窗口最大长度为一天的累计窗口,窗口滚动步长为1分钟 CUMULATE( TABLE dt_catalog.dt_db.orders, DESCRIPTOR(order_time), INTERVAL '1' MINUTES, INTERVAL '1' DAY)) GROUP BY window_start, window_end; --********************************************************************-- -- Flink SQL 快速入门示例 会话窗口聚合 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.server_logs ( client_ip STRING, client_identity STRING, userid STRING, log_time TIMESTAMP(3), request_line STRING, status_code STRING, WATERMARK FOR log_time AS log_time - INTERVAL '5' SECONDS -- 定义 watermark ) WITH ( 'connector' = 'faker', 'rows-per-second' = '5', 'fields.client_ip.expression' = '#{Internet.publicIpV4Address}', 'fields.client_identity.expression' = '-', 'fields.userid.expression' = '#{regexify ''(morsapaes|knauf|sjwiesman){1}''}', 'fields.log_time.expression' = '#{date.past ''5'',''SECONDS''}', 'fields.request_line.expression' = '#{regexify ''(GET|POST|PUT|PATCH){1}''} #{regexify ''(/search\.html|/login\.html|/prod\.html|cart\.html|/order\.html){1}''} #{regexify ''(HTTP/1\.1|HTTP/2|/HTTP/1\.0){1}''}', 'fields.status_code.expression' = '#{regexify ''(200|201|204|400|401|403|301){1}''}' ); SELECT userid, SESSION_START(log_time, INTERVAL '10' SECOND) AS session_beg, SESSION_ROWTIME(log_time, INTERVAL '10' SECOND) AS session_end, COUNT(request_line) AS request_cnt FROM dt_catalog.dt_db.server_logs WHERE status_code = '403' GROUP BY userid, -- 会话窗口的最大空闲间隔为10s,当10s内该窗口没有接收到新的请求,会关闭当前窗口 SESSION(log_time, INTERVAL '10' SECOND); --********************************************************************-- -- Flink SQL 快速入门示例 OVER窗口聚合 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.temperature_measurements ( measurement_time TIMESTAMP(3), city STRING, temperature FLOAT, WATERMARK FOR measurement_time AS measurement_time - INTERVAL '15' SECONDS -- 定义时间属性字段,OVER窗口排序时使用 ) WITH ( 'connector' = 'faker', -- Faker 连接器仅在 VVR-4.0.12 及以上支持 'fields.measurement_time.expression' = '#{date.past ''15'',''SECONDS''}', 'fields.temperature.expression' = '#{number.numberBetween ''0'',''50''}', 'fields.city.expression' = '#{regexify ''(Chicago|Munich|Berlin|Portland|Hangzhou|Seatle|Beijing|New York){1}''}' ); SELECT measurement_time, city, temperature, AVG(CAST(temperature AS FLOAT)) OVER last_minute AS avg_temperature_minute, -- 计算平均值 MAX(temperature) OVER last_minute AS min_temperature_minute, -- 计算最大值 MIN(temperature) OVER last_minute AS max_temperature_minute, -- 计算最小值 STDDEV(CAST(temperature AS FLOAT)) OVER last_minute AS stdev_temperature_minute -- 计算标准差 FROM dt_catalog.dt_db.temperature_measurements WINDOW last_minute AS ( -- 定义1min时间间隔的OVER窗口,按城市粒度分区,温度测量值排序,每个元素都会触发一次计算 PARTITION BY city ORDER BY measurement_time RANGE BETWEEN INTERVAL '1' MINUTE PRECEDING AND CURRENT ROW ); --********************************************************************-- -- Flink SQL 快速入门示例 级联窗口聚合 --********************************************************************-- CREATE TEMPORARY TABLE server_logs ( log_time TIMESTAMP(3), client_ip STRING, client_identity STRING, userid STRING, request_line STRING, status_code STRING, size INT, WATERMARK FOR log_time AS log_time - INTERVAL '15' SECONDS -- 定义watermark ) WITH ( 'connector' = 'faker', 'fields.log_time.expression' = '#{date.past ''15'',''5'',''SECONDS''}', 'fields.client_ip.expression' = '#{Internet.publicIpV4Address}', 'fields.client_identity.expression' = '-', 'fields.userid.expression' = '-', 'fields.request_line.expression' = '#{regexify ''(GET|POST|PUT|PATCH){1}''} #{regexify ''(/search\.html|/login\.html|/prod\.html|cart\.html|/order\.html){1}''} #{regexify ''(HTTP/1\.1|HTTP/2|/HTTP/1\.0){1}''}', 'fields.status_code.expression' = '#{regexify ''(200|201|204|400|401|403|301){1}''}', 'fields.size.expression' = '#{number.numberBetween ''100'',''10000000''}' ); -- 1min聚合结果表 CREATE TEMPORARY TABLE avg_request_size_1m ( window_start TIMESTAMP(3), window_end TIMESTAMP(3), avg_size BIGINT ) WITH ( 'connector' = 'blackhole' ); -- 5min聚合结果表 CREATE TEMPORARY TABLE avg_request_size_5m ( window_start TIMESTAMP(3), window_end TIMESTAMP(3), avg_size BIGINT ) WITH ( 'connector' = 'blackhole' ); -- 1min窗口查询结果 CREATE VIEW server_logs_window_1m AS SELECT TUMBLE_START(log_time, INTERVAL '1' MINUTE) AS window_start, TUMBLE_ROWTIME(log_time, INTERVAL '1' MINUTE) AS window_end, SUM(size) AS total_size, COUNT(*) AS num_requests FROM server_logs GROUP BY TUMBLE(log_time, INTERVAL '1' MINUTE); -- 基于1min窗口查询结果,进行5min粒度窗口聚合 CREATE VIEW server_logs_window_5m AS SELECT TUMBLE_START(window_end, INTERVAL '5' MINUTE) AS window_start, TUMBLE_ROWTIME(window_end, INTERVAL '5' MINUTE) AS window_end, SUM(total_size) AS total_size, SUM(num_requests) AS num_requests FROM server_logs_window_1m GROUP BY TUMBLE(window_end, INTERVAL '5' MINUTE); BEGIN STATEMENT SET; -- 写入结果到1min窗口粒度结果表 INSERT INTO avg_request_size_1m SELECT window_start, window_end, total_size/num_requests AS avg_size FROM server_logs_window_1m; -- 写入结果到5min窗口粒度结果表 INSERT INTO avg_request_size_5m SELECT window_start, window_end, total_size/num_requests AS avg_size FROM server_logs_window_5m; END; --********************************************************************-- -- Flink SQL 快速入门示例 去重 -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.orders ( id INT, order_time AS CURRENT_TIMESTAMP, WATERMARK FOR order_time AS order_time - INTERVAL '5' SECONDS ) WITH ( 'connector' = 'datagen', 'rows-per-second'='10', 'fields.id.kind'='random', 'fields.id.min'='1', 'fields.id.max'='100' ); -- 对于每个order_id,按事件时间去重,只保留最新时间的记录即可实现去重 SELECT order_id, order_time FROM ( SELECT id AS order_id, order_time, -- 按事件时间升序排序 ROW_NUMBER() OVER (PARTITION BY id ORDER BY order_time) AS rownum FROM dt_catalog.dt_db.orders) WHERE rownum = 1; -- 只取排名第一的记录,去重是Top-N的一种特例 --********************************************************************-- -- Flink SQL 快速入门示例 Top-N -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.spells_cast ( wizard STRING, spell STRING ) WITH ( 'connector' = 'faker', 'fields.wizard.expression' = '#{harry_potter.characters}', 'fields.spell.expression' = '#{harry_potter.spells}' ); -- 找出每个巫师最喜欢的两个法术 SELECT wizard, spell, times_cast FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY wizard ORDER BY times_cast DESC) AS row_num -- 按法术次数降序排序 FROM (SELECT wizard, spell, COUNT(*) AS times_cast FROM dt_catalog.dt_db.spells_cast GROUP BY wizard, spell) -- 计算每个巫师施展的各种法术的次数 ) WHERE row_num <= 2; --********************************************************************-- -- Flink SQL 快速入门示例 窗口Top-N -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.orders ( bidtime TIMESTAMP(3), price DOUBLE, item STRING, supplier STRING, WATERMARK FOR bidtime AS bidtime - INTERVAL '5' SECONDS -- 定义watermark ) WITH ( 'connector' = 'faker', 'fields.bidtime.expression' = '#{date.past ''30'',''SECONDS''}', 'fields.price.expression' = '#{Number.randomDouble ''2'',''1'',''150''}', 'fields.item.expression' = '#{Commerce.productName}', 'fields.supplier.expression' = '#{regexify ''(Alice|Bob|Carol|Alex|Joe|James|Jane|Jack)''}', 'rows-per-second' = '100' ); -- 取出销售排名前三的供应商 SELECT * FROM ( -- 按窗口时间分区,按价格降序排序 SELECT *, ROW_NUMBER() OVER (PARTITION BY window_start, window_end ORDER BY price DESC) AS rownum FROM ( -- 计算每个窗口内各个供应商的销售额 SELECT window_start, window_end, supplier, SUM(price) AS price, COUNT(*) AS cnt FROM TABLE( TUMBLE(TABLE dt_catalog.dt_db.orders, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES)) GROUP BY window_start, window_end, supplier ) ) WHERE rownum <= 3; --********************************************************************-- -- Flink SQL 快速入门示例 模式检测CEP -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.subscriptions ( id STRING, user_id INT, type STRING, start_date TIMESTAMP(3), end_date TIMESTAMP(3), payment_expiration TIMESTAMP(3), proc_time AS PROCTIME() ) WITH ( 'connector' = 'faker', 'fields.id.expression' = '#{Internet.uuid}', 'fields.user_id.expression' = '#{number.numberBetween ''1'',''50''}', 'fields.type.expression'= '#{regexify ''(basic|premium|platinum){1}''}', 'fields.start_date.expression' = '#{date.past ''30'',''DAYS''}', 'fields.end_date.expression' = '#{date.future ''15'',''DAYS''}', 'fields.payment_expiration.expression' = '#{date.future ''365'',''DAYS''}' ); SELECT * FROM dt_catalog.dt_db.subscriptions MATCH_RECOGNIZE ( -- 按user_id分区,按处理时间proc_time升序排序 PARTITION BY user_id ORDER BY proc_time MEASURES LAST(PREMIUM.type) AS premium_type, AVG(TIMESTAMPDIFF(DAY,PREMIUM.start_date,PREMIUM.end_date)) AS premium_avg_duration, BASIC.start_date AS downgrade_date AFTER MATCH SKIP PAST LAST ROW --模式: 一个或多个‘premium‘或’platinum‘订阅事件 --对于相同的'user_id',后面跟着一个'basic'订阅事件 PATTERN (PREMIUM+ BASIC) DEFINE PREMIUM AS PREMIUM.type IN ('premium','platinum'), BASIC AS BASIC.type = 'basic'); --********************************************************************-- -- Flink SQL 快速入门示例 Regular Join -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.NOC ( agent_id STRING, codename STRING ) WITH ( 'connector' = 'faker', 'fields.agent_id.expression' = '#{regexify ''(1|2|3|4|5){1}''}', 'fields.codename.expression' = '#{superhero.name}', 'number-of-rows' = '10' ); CREATE TABLE dt_catalog.dt_db.RealNames ( agent_id STRING, name STRING ) WITH ( 'connector' = 'faker', 'fields.agent_id.expression' = '#{regexify ''(1|2|3|4|5){1}''}', 'fields.name.expression' = '#{Name.full_name}', 'number-of-rows' = '10' ); -- 使用agent_id作为两张表关联的条件,左右两边任何一张表来了新数据都会触发join动作 SELECT name, codename FROM dt_catalog.dt_db.NOC t1 INNER JOIN dt_catalog.dt_db.RealNames t2 ON t1.agent_id = t2.agent_id; --********************************************************************-- -- Flink SQL 快速入门示例 Interval Join -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.orders ( id INT, order_time AS TIMESTAMPADD(DAY, CAST(FLOOR(RAND()*(1-5+1)+5)*(-1) AS INT), CURRENT_TIMESTAMP) ) WITH ( 'connector' = 'datagen', 'rows-per-second'='10', 'fields.id.kind'='sequence', 'fields.id.start'='1', 'fields.id.end'='1000' ); CREATE TABLE dt_catalog.dt_db.shipments ( id INT, order_id INT, shipment_time AS TIMESTAMPADD(DAY, CAST(FLOOR(RAND()*(1-5+1)) AS INT), CURRENT_TIMESTAMP) ) WITH ( 'connector' = 'datagen', 'rows-per-second'='5', 'fields.id.kind'='random', 'fields.id.min'='0', 'fields.order_id.kind'='sequence', 'fields.order_id.start'='1', 'fields.order_id.end'='1000' ); -- order表的每条数据会与shipments表过去三天至当前时刻时间范围内的数据进行join SELECT o.id AS order_id, o.order_time, s.shipment_time, TIMESTAMPDIFF(DAY,o.order_time,s.shipment_time) AS day_diff FROM dt_catalog.dt_db.orders o JOIN dt_catalog.dt_db.shipments s ON o.id = s.order_id WHERE -- 时间 join 条件:shipments.shipment_time - INTERVAL '3' DAY <= orders.order_time < shipments.shipment_time o.order_time BETWEEN s.shipment_time - INTERVAL '3' DAY AND s.shipment_time; --********************************************************************-- -- Flink SQL 快速入门示例 时态表Join -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- -- 使用主键约束和watermark来定义一张版本表,这张表可以是一个cdc表、upsert类型的kafka topic等 CREATE TABLE dt_catalog.dt_db.currency_rates ( `currency_code` STRING, `eur_rate` DECIMAL(6,4), `rate_time` TIMESTAMP(3), WATERMARK FOR `rate_time` AS rate_time - INTERVAL '15' SECONDS, -- 定义事件时间 PRIMARY KEY (currency_code) NOT ENFORCED -- 定义主键 ) WITH ( 'connector' = 'faker', 'fields.currency_code.expression' = '#{Currency.code}', 'fields.eur_rate.expression' = '#{Number.randomDouble ''4'',''0'',''10''}', 'fields.rate_time.expression' = '#{date.past ''15'',''SECONDS''}', 'rows-per-second' = '100' ); -- 这是一个append-only类型的动态表,需要定义watermk CREATE TABLE dt_catalog.dt_db.transactions ( `id` STRING, `currency_code` STRING, `total` DECIMAL(10,2), `transaction_time` TIMESTAMP(3), WATERMARK FOR `transaction_time` AS transaction_time - INTERVAL '30' SECONDS --定义watermark ) WITH ( 'connector' = 'faker', 'fields.id.expression' = '#{Internet.UUID}', 'fields.currency_code.expression' = '#{Currency.code}', 'fields.total.expression' = '#{Number.randomDouble ''2'',''10'',''1000''}', 'fields.transaction_time.expression' = '#{date.past ''30'',''SECONDS''}', 'rows-per-second' = '100' ); -- 当左右两张表的watermark对齐时,才会触发join动作,左右两张表都需要定义watermark SELECT t.id, t.total * c.eur_rate AS total_eur, t.total, c.currency_code, t.transaction_time FROM dt_catalog.dt_db.transactions t -- transactions表每条记录都与currency_rates表transaction_time时刻的汇率进行join JOIN dt_catalog.dt_db.currency_rates FOR SYSTEM_TIME AS OF t.transaction_time AS c -- 指定join key ON t.currency_code = c.currency_code; --********************************************************************-- -- Flink SQL 快速入门示例 维表Join -- 该模版仅支持使用"执行"功能。如需"提交"运行,需要您增加 INSERT 相关逻辑 --********************************************************************-- CREATE TABLE dt_catalog.dt_db.subscriptions ( id STRING, user_id INT, type STRING, start_date TIMESTAMP(3), end_date TIMESTAMP(3), payment_expiration TIMESTAMP(3), proc_time AS PROCTIME() -- 这里需要定义处理时间属性 ) WITH ( 'connector' = 'faker', 'fields.id.expression' = '#{Internet.uuid}', 'fields.user_id.expression' = '#{number.numberBetween ''1'',''50''}', 'fields.type.expression'= '#{regexify ''(basic|premium|platinum){1}''}', 'fields.start_date.expression' = '#{date.past ''30'',''DAYS''}', 'fields.end_date.expression' = '#{date.future ''365'',''DAYS''}', 'fields.payment_expiration.expression' = '#{date.future ''365'',''DAYS''}' ); -- 定义维表,为了示例能直接运行,这里使用faker 作为维表,实际应用中一般会使用JDBC、Redis、Hbase等作为维表 CREATE TABLE dt_catalog.dt_db.users ( user_id INT PRIMARY KEY, -- 定义主键 user_name VARCHAR(255) NOT NULL, age INT NOT NULL ) WITH ( 'connector' = 'faker', 'fields.user_id.expression' = '#{number.numberBetween ''1'',''10''}', 'fields.user_name.expression' = '#{regexify ''(ron|jark|danny){1}''}', 'fields.age.expression' = '#{number.numberBetween ''1'',''30''}' ); SELECT id AS subscription_id, type AS subscription_type, age AS user_age, CASE WHEN age < 18 THEN 1 ELSE 0 END AS is_minor FROM dt_catalog.dt_db.subscriptions usub -- subscriptions每条记录都使用当前系统时间与维表users中的最新数据进行join JOIN dt_catalog.dt_db.users FOR SYSTEM_TIME AS OF usub.proc_time AS u -- 指定join key ON usub.user_id = u.user_id; --********************************************************************-- -- Flink SQL ODS 层 -- 实际应用中,该任务应该是一个采集任务,源表为RDB --********************************************************************-- CREATE TABLE source_table ( account_number STRING, channel_id INT, account_open_datetime TIMESTAMP(3) ) WITH ( 'connector' = 'faker', -- 使用 Flink Faker Connector 'fields.account_number.expression' = '#{Finance.iban}', -- 随机生成银行账号 'fields.channel_id.expression' = '#{number.numberBetween ''1'',''4''}', -- 渠道ID随机生成1到3之间的数字 'fields.account_open_datetime.expression' = '#{date.past ''15'',''5'',''SECONDS''}' -- 过去15天的日期,每5秒一条数据 ); -- 定义结果表,实际应用中应选择 Kafka等作为结果表 CREATE TABLE sink_table ( account_number STRING, channel_id INT, account_open_datetime TIMESTAMP(3) ) WITH ( 'connector' = 'stream-x' ); -- 写入数据到结果表 INSERT INTO sink_table SELECT * FROM source_table --********************************************************************-- -- Flink SQL DWD 层 -- 实际应用中,源表为 ODS TOPIC --********************************************************************-- CREATE TABLE source_table ( account_number STRING, channel_id INT, account_open_datetime TIMESTAMP(3) ) WITH ( 'connector' = 'faker', -- 使用 Flink Faker Connector 'fields.account_number.expression' = '#{Finance.iban}', -- 随机生成银行账号 'fields.channel_id.expression' = '#{number.numberBetween ''1'',''4''}', -- 渠道ID随机生成1到3之间的数字 'fields.account_open_datetime.expression' = '#{date.past ''15'',''5'',''SECONDS''}' -- 过去15天的日期,每5秒一条数据 ); -- 定义维表,实际应用中应选择RDB作为维表 CREATE TABLE dim_table ( channel_id INT, channel_name STRING, PRIMARY KEY (channel_id,channel_name) NOT ENFORCED ) WITH ( 'connector' = 'faker', -- 使用 Flink Faker Connector 'fields.channel_id.expression' = '#{number.numberBetween ''1'',''4''}', -- 渠道ID随机生成1到3之间的数字 'fields.channel_name.expression' = '#{app.name}' -- 渠道名称 ); -- 定义结果表,实际应用中应选择 Kafka等作为结果表 CREATE TABLE sink_table ( account_number STRING, channel_id INT, channel_name STRING, account_open_datetime TIMESTAMP(3) ) WITH ( 'connector' = 'stream-x' ); -- 写入数据到结果表 INSERT INTO sink_table SELECT s1.account_number, s1. channel_id , d1.channel_name, s1.account_open_datetime FROM source_table s1 left JOIN dim_table d1 ON s1.channel_id=d1.channel_id --********************************************************************-- -- Flink SQL DWS 层 -- 实际应用中,源表为DWD TOPIC --********************************************************************-- CREATE TABLE source_table ( account_number STRING, channel_id INT, channel_name STRING, account_open_datetime TIMESTAMP(3) ) WITH ( 'connector' = 'faker', -- 使用 Flink Faker Connector 'fields.account_number.expression' = '#{Finance.iban}', -- 随机生成银行账号 'fields.channel_id.expression' = '#{number.numberBetween ''1'',''4''}', -- 渠道ID随机生成1到3之间的数字 'fields.channel_name.expression' = '#{app.name}' ,-- 渠道名称 'fields.account_open_datetime.expression' = '#{date.past ''15'',''5'',''SECONDS''}' -- 过去15天的日期,每5秒一条数据 ); DROP TABLE source_table SELECT * FROM source_table -- 定义结果表,实际应用中应选择Kafka作为结果表 CREATE TABLE sink_table ( channel_id STRING, open_date STRING, cnt INT ) WITH ( 'connector' = 'stream-x' ); DROP TABLE sink_table SELECT * FROM sink_table -- 写入数据到结果表 INSERT INTO sink_table SELECT channel_id, DATE_FORMAT(account_open_datetime,'yyyy-MM-dd'), count(account_number) FROM source_table GROUP BY channel_id,DATE_FORMAT(account_open_datetime,'yyyy-MM-dd') --********************************************************************-- -- Flink SQL ADS 层 -- 实际应用中,源表为DWS TOPIC --********************************************************************-- CREATE TABLE source_table ( channel_id STRING, open_time TIMESTAMP(3), cnt INT ) WITH ( 'connector' = 'faker', -- 使用 Flink Faker Connector 'fields.channel_id.expression' = '#{number.numberBetween ''1'',''4''}', -- 渠道ID随机生成1到3之间的数字 'fields.open_time.expression' = '#{Date.future ''15'',''5'',''SECONDS''}' ,-- 日期 'fields.cnt.expression' = '#{number.numberBetween ''1'',''100000000''}'-- 数量 ); -- 实际应用中,结果表为RDB CREATE TABLE sink_table ( open_date STRING, cnt INT ) WITH ( 'connector' = 'stream-x' ); -- 写入数据到结果表 INSERT INTO sink_table SELECT DATE_FORMAT(open_time,'yyyy-MM-dd'),count(1);