Flink Table & SQL ROW_NUMBER Deduplication

本文详细介绍如何在FlinkSQL中使用ROW_NUMBER()函数进行数据去重操作,包括语法、注意事项及代码示例,适用于BlinkPlanner环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Flink SQL中用ROW_NUMBER进行去重操作。

语法

SELECT [column_list]
FROM (
   SELECT [column_list],
     ROW_NUMBER() OVER ([PARTITION BY col1[, col2...]]
       ORDER BY time_attr_col [asc|desc]) AS rownum
   FROM table_name)
WHERE rownum = 1

说明

  • ROW_NUMBER(): 给分区内的每行数据分配一个唯一的序号(从1开始)。

  • PARTITION BY col1[, col2...]: 指定分区列,即去重的Keys。

  • ORDER BY time_attr_col [asc|desc]): 指定排序列。时间属性目前仅支持proctime,暂不支持rowtime。按asc排序保留第一条,按desc排序保留最后一条。

注意:

  1. 需要两层Query:

    • 内层查询使用ROW_NUMBER() OVER窗口函数对分区内(通过PARTITION BY指定)的数据根据排序列(通过ORDER BY指定)标上排名(rownum)。

    • 外层查询对排名取第一个。

  2. 外层查询WHERE条件中,必须通过如rownum = 1指定,Flink才能将其识别为去重操作。

  3. 会产生Retraction。

  4. 仅支持Blink Planner。

用ROW_NUMBER去重

测试数据

//自己造的测试数据,如下:
//某个用户在某个时刻点击了某个商品
{"userID":"user_1","eventType":"click","eventTime":"2015-01-01 01:00:00","productID":"product_1"}

代码示例

package com.bigdata.flink.deduplication;

import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.EnvironmentSettings;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.java.StreamTableEnvironment;
import org.apache.flink.types.Row;

/**
 * Author: Wang Pei
 * Summary:
 * RowNumber Deduplication
 */
public class RowNumberDeduplication {
    public static void main(String[] args) throws Exception {

        EnvironmentSettings settings = EnvironmentSettings.newInstance().inStreamingMode().useBlinkPlanner().build();
        StreamExecutionEnvironment streamEnv = StreamExecutionEnvironment.getExecutionEnvironment();
        StreamTableEnvironment tableEnv = StreamTableEnvironment.create(streamEnv, settings);

        // Source DDL
        String sourceDDL = ""
                + "create table source_kafka "
                + "( "
                + "    userID String, "
                + "    eventType String, "
                + "    eventTime String, "
                + "    productID String, "
                + "    proctime AS PROCTIME() "
                + ") with ( "
                + "    'connector.type' = 'kafka', "
                + "    'connector.version' = '0.10', "
                + "    'connector.properties.bootstrap.servers' = 'kafka01:9092', "
                + "    'connector.properties.zookeeper.connect' = 'kafka01:2181', "
                + "    'connector.topic' = 'test_1', "
                + "    'connector.properties.group.id' = 'c1_test_1', "
                + "    'connector.startup-mode' = 'latest-offset', "
                + "    'format.type' = 'json' "
                + ")";
        tableEnv.sqlUpdate(sourceDDL);
        //tableEnv.toAppendStream(tableEnv.from("source_kafka"), Row.class).print();

        // Deduplication Query
        // 保留最后一条
        String execSQL = ""
                + "SELECT userID, eventType, eventTime, productID  "
                + "FROM ( "
                + "  SELECT *, "
                + "     ROW_NUMBER() OVER (PARTITION BY userID, eventType, eventTime ORDER BY proctime DESC) AS rownum "
                + "  FROM source_kafka "
                + ") t "
                + "WHERE rownum = 1";
        Table resultTable = tableEnv.sqlQuery(execSQL);
        tableEnv.toRetractStream(resultTable, Row.class).print();

        tableEnv.execute(RowNumberDeduplication.class.getSimpleName());
    }
}

结果查看

// Kafka中逐条输入如下数据
{"userID":"user_1","eventType":"click","eventTime":"2015-01-01 01:00:00","productID":"product_1"}
{"userID":"user_1","eventType":"click","eventTime":"2015-01-01 01:00:00","productID":"product_2"}
{"userID":"user_1","eventType":"click","eventTime":"2015-01-01 01:00:00","productID":"product_3"}

// 输出
(true,user_1,click,2015-01-01 01:00:00,product_1)
(false,user_1,click,2015-01-01 01:00:00,product_1)
(true,user_1,click,2015-01-01 01:00:00,product_2)
(false,user_1,click,2015-01-01 01:00:00,product_2)
(true,user_1,click,2015-01-01 01:00:00,product_3)
Flink SQL中,批处理使用ROW_NUMBER函数来对数据进行编号。ROW_NUMBER函数用于为每一行数据分配一个唯一的编号,这个编号可以作为数据的排序依据或者用于分页操作。在批处理中,ROW_NUMBER函数可以用于将数据按照指定的排序规则进行编号,并且可以根据需要对数据进行筛选或者分组。 使用ROW_NUMBER函数的语法如下: ``` ROW_NUMBER() OVER (ORDER BY column1, column2, ...) ``` 其中,ORDER BY子句用于指定排序的列,可以指定多个列进行排序。使用ROW_NUMBER函数后,每一行数据都会被赋予一个唯一的编号。 通过使用ROW_NUMBER函数,可以方便地对批处理数据进行排序和分页操作。但是需要注意的是,ROW_NUMBER函数在处理大规模数据时可能会影响性能。因此,在使用时需要根据实际情况进行评估和优化,以确保程序的性能和效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [sqlServer使用ROW_NUMBER时不排序的解决方法](https://download.csdn.net/download/weixin_38606169/14834301)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Flink SQL 批处理使用HOP详解](https://blog.csdn.net/Scapel/article/details/115251669)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值