SQL查询:区间数量统计|关于elt(数组取值)和INTERVAL(区间定位)的用法

本文介绍了如何使用SQL的group by、having、elt和INTERVAL函数来实现对数据的高级统计分析。包括找出发博量大于1000的用户并排序,计算平均发博量,以及利用elt和INTERVAL进行发博区间的人数统计。INTERVAL函数用于区间定位,而elt函数则用于根据给定的下标获取数组值。

基本需求

找到发博量大于1000的用户并排序:group by + having

select count(*) as num,uid from status group by uid 
having(count(*)>1000) order by count(*) desc

在这里插入图片描述

统计平均发博量:group by+子查询

select avg(a.num) from 
(select count(*) as num,uid from status group by uid )as a

在这里插入图片描述

进阶需求

按照发博区间统计人数:elt+INTERVAL

SELECT elt(
INTERVAL(a.num, 0, 5, 10, 50, 100, 500, 1000), 
'<5', '5-10', '10-50', '50-100', '100-500', '500-1000', '>=1000') 
as num, count(uid) as user_num
FROM (select count(*) as num,uid from status group by uid ) as a
GROUP BY elt(
INTERVAL(a.num, 0, 5, 10, 50, 100, 500, 1000), 
'<5', '5-10', '10-50', '50-100', '100-500', '500-1000', '>=1000')
 order by user_num desc  

在这里插入图片描述

INTERVAL:区间定位

INTERVAL(N,N1,N2,N3,…)
INTERVAL()函数用于定位N在后续N1、N2、N3…组成区间的位置,列表值要求满足N1<N2<N3…。返回所在区间下标。
在这里插入图片描述

elt:数组取值

ELT(N,N1,N2,N3,…)
如果N=1则返回N1,如果N=2则返回N2,如果N=3则返回N3
elt+INTERVAL
在这里插入图片描述

# 深入浅出讲解ELT与FlinkSQL ## 一、ELT原理详解(用厨房做类比) ### 1. ELT是什么? 想象你是个厨师: - **E (Extract)**:从菜市场采购食材(从MySQL/Kafka等抽据) - **L (Load)**:把食材放进厨房(原始据加载到存储系统) - **T (Transform)**:在厨房进行烹饪(在存储层进行据转换) 对比传统ETL: ```mermaid graph LR ETL模式:据源-->清洗-->加载-->目标库 ELT模式:据源-->加载-->清洗-->目标库 ``` ### 2. 为什么选择ELT? - 🚀 **更快速**:先加载后转换,适合大据量 - 💰 **更经济**:利用现代据库的计算能力 - 🔄 **更灵活**:随时可以重新转换据 ## 二、FlinkSQL实现ELT的三大优势 ### 优势1:统一批流处理 ```sql -- 同样的SQL既能处理历史据也能处理实时据 INSERT INTO user_orders_summary SELECT user_id, COUNT(*) FILTER (WHERE dt = '2023-01-01') AS yesterday_count, COUNT(*) FILTER (WHERE dt = '2023-01-02') AS today_count FROM orders GROUP BY user_id; ``` ### 优势2:内置强大的连接器 | 连接器类型 | 示例据源 | 使用场景 | |-----------|-----------------------|------------------------| | CDC | MySQL/Oracle | 实时捕获据库变更 | | Message | Kafka/Pulsar | 处理消息队列| | File | HDFS/S3 | 分析文件| | JDBC | 任意关系型据库 | 结果输出或维表关联 | ### 优势3:完善的窗口机制 ```sql -- 滚动窗口(每5分钟统计) SELECT window_start, window_end, SUM(amount) FROM TABLE( TUMBLE(TABLE orders, DESCRIPTOR(order_time), INTERVAL '5' MINUTES) ) GROUP BY window_start, window_end; -- 滑动窗口(每5分钟统计,滑动间隔1分钟) SELECT window_start, window_end, COUNT(*) FROM TABLE( HOP(TABLE orders, DESCRIPTOR(order_time), INTERVAL '1' MINUTES, INTERVAL '5' MINUTES) ) GROUP BY window_start, window_end; ``` ## 三、典型ELT流程示例(电商场景) ### 步骤1:原始据加载 ```sql CREATE TABLE source_orders ( order_id STRING, user_id INT, amount DECIMAL(10,2), order_time TIMESTAMP(3), METADATA FROM 'value.source.timestamp' VIRTUAL -- 记录据源时间 ) WITH ( 'connector' = 'kafka', 'topic' = 'orders', 'properties.bootstrap.servers' = 'kafka:9092' ); ``` ### 步骤2:据转换 ```sql -- 创建目标表 CREATE TABLE dw_order_analysis ( dt DATE, user_id INT, order_count BIGINT, total_amount DECIMAL(16,2), PRIMARY KEY (dt, user_id) NOT ENFORCED ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://mysql:3306/dw', 'table-name' = 'order_analysis' ); -- 执行转换 INSERT INTO dw_order_analysis SELECT CAST(order_time AS DATE) AS dt, user_id, COUNT(*) AS order_count, SUM(amount) AS total_amount FROM source_orders GROUP BY CAST(order_time AS DATE), user_id; ``` ### 步骤3:质量监控 ```sql -- 据质量检查SQL CREATE TABLE data_quality_monitor ( check_time TIMESTAMP(3), metric_name STRING, metric_value DECIMAL(16,2) ) WITH (...); INSERT INTO data_quality_monitor SELECT CURRENT_TIMESTAMP, 'order_amount_avg' AS metric_name, AVG(amount) AS metric_value FROM source_orders WHERE order_time > CURRENT_TIMESTAMP - INTERVAL '1' HOUR; ``` ## 四、常见问题解决方案 ### 问题1:如何保证据一致性? ```sql -- 启用精确一次语义 SET 'execution.checkpointing.interval' = '30s'; SET 'execution.checkpointing.mode' = 'EXACTLY_ONCE'; ``` ### 问题2:维表关联如何优化? ```sql CREATE TABLE dim_user ( user_id INT, vip_level INT ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://mysql:3306/dim', 'table-name' = 'user_info', 'lookup.cache.max-rows' = '10000', -- 缓存1万条 'lookup.cache.ttl' = '10min' -- 缓存10分钟 ); -- 关联查询 SELECT o.order_id, o.amount, d.vip_level FROM orders o JOIN dim_user FOR SYSTEM_TIME AS OF o.order_time AS d ON o.user_id = d.user_id; ``` ### 问题3:如何处理迟到据? ```sql -- 定义水位线允许延迟2分钟 CREATE TABLE orders ( order_id STRING, order_time TIMESTAMP(3), WATERMARK FOR order_time AS order_time - INTERVAL '2' MINUTE ) WITH (...); -- 窗口允许延迟1分钟 SELECT window_start, window_end, COUNT(*) FROM TABLE( TUMBLE(TABLE orders, DESCRIPTOR(order_time), INTERVAL '5' MINUTES) ) GROUP BY window_start, window_end -- 允许延迟据触发计算 WITH LATE DATA DELAY BY INTERVAL '1' MINUTE; ``` ## 五、最佳实践建议 1. **开发规范**: - 使用`SCHEMA EVOLUTION`处理表结构变更 - SQL脚本按业务域分目录存储 - 重要作业添加据质量监控 2. **性能调优**: ```sql -- 设置状态保留时间 SET 'table.exec.state.ttl' = '7d'; -- 调整并行度 SET 'parallelism.default' = '8'; ``` 3. **运维监控**: ```bash # 常用监控指标 flink_jobmanager_numRunningJobs flink_taskmanager_job_latency_source_id=... jvm_memory_used{area="heap"} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值