数据可视化BI宽表到窄表转换方案探索:如AntV G2 transform.fold
Author:zhoulujun Date:
数据库层面:什么是窄表?什么是宽表?
在数据库中,窄表和宽表是两种设计思想,分别指的是列数少或者列数多的表格。
窄表是指只包含少量列(如主键和几个属性)的表格。这种设计思想用于解决单一业务场景下的数据存储及访问问题,从而提高查询效率,减少存储空间。通常应用于 OLTP(联机事务处理)这样的在线事务处理系统。关系型数据库中大部分的表都是窄表。
存储空间占用少:窄表只包含必要的字段,减少了存储空间的占用。
查询效率高:窄表中字段较少,减少了表关联操作,提高了查询效率。
数据结构清晰:窄表设计简洁明了,易于维护和管理。
宽表则是指具有大量列的表格。这些列可以来自不同的来源,可能包括各种聚合和汇总数据等。宽表用于存储冗长的数据,以支持分析和挖掘等复杂查询,通常应用于 OLAP(联机分析处理)这样的在线分析处理系统。宽表能够提供更为全面和详细的数据,但同时也会带来一定的复杂度,包括查询效率下降等问题。
减少表关联:宽表中包含了更多的冗余字段或关联字段,减少了表关联操作,提高了查询效率。
数据冗余:宽表中的冗余字段可以减少查询时的数据访问次数,提高查询速度。
查询性能优化:宽表可以通过预先计算复杂的数据计算结果,提高查询性能。
可视化层面:什么是窄表?什么是宽表?
宽表(wide)
一行包含多个指标:
| catid | sum_views | count_views | avg_views |
|---|---|---|---|
| 53 | 11484 | 19 | 604.4 |
| 54 | 0 | 1 | 0 |
select * from demo_table
但是图表,无论是echarts、antV G2、D3 等,都无法直接渲染这样的数据
窄表(long)
每行只包含一个指标:
| catid | metric | value |
|---|---|---|
| 53 | sum_views | 11484 |
| 53 | count_views | 19 |
| 53 | avg_views | 604.4 |
| 54 | sum_views | 0 |
| … | … | … |
而这样的sql查询是时候,sql组装就复杂的的多了
最好用的 SQL 写法(兼容 MySQL 8.0+ / PostgreSQL / ClickHouse / Doris 等现代数据库):
SELECT
catid::TEXT AS catid, -- 维度
'求和views' AS metric, -- 图例名称(中文)
SUM(views) AS value
FROM v9_hits
GROUP BY catid
UNION ALL VALUES -- MySQL 8.0+ / PostgreSQL / Doris 等支持的语法糖
('求和views', SUM(views)),
('求和monthviews', SUM(monthviews)),
('最小值views', MIN(views)),
('最大值views', MAX(views)),
('计数views', COUNT(views)),
('去重计数views', COUNT(DISTINCT views)),
('平均值views', AVG(views)::DECIMAL(10,4))
-- 如果你的数据库还不支持 VALUES 语法,就用最经典的 UNION ALL(万能版):万能版(所有数据库都支持):
SELECT catid::TEXT AS catid, '求和views' AS metric, SUM(views) AS value FROM v9_hits GROUP BY catid UNION ALL SELECT catid::TEXT AS catid, '求和monthviews' AS metric, SUM(monthviews) AS value FROM v9_hits GROUP BY catid UNION ALL SELECT catid::TEXT AS catid, '最小值views' AS metric, MIN(views) AS value FROM v9_hits GROUP BY catid UNION ALL SELECT catid::TEXT AS catid, '最大值views' AS metric, MAX(views) AS value FROM v9_hits GROUP BY catid UNION ALL SELECT catid::TEXT AS catid, '计数views' AS metric, COUNT(views) AS value FROM v9_hits GROUP BY catid UNION ALL SELECT catid::TEXT AS catid, '去重计数views' AS metric, COUNT(DISTINCT views) AS value FROM v9_hits GROUP BY catid UNION ALL SELECT catid::TEXT AS catid, '平均值views' AS metric, AVG(views) AS value FROM v9_hits GROUP BY catid ORDER BY catid, metric;
返回结果就是完美长表:
| catid | metric | value |
|---|---|---|
| 53 | 求和views | 11484 |
| 53 | 平均值views | 604.4211 |
| 54 | 求和views | 0 |
| ... | ... | ... |
但是,如果你前端既需要展示表格视图,又需要展示图表视图,这个时候后端出两种格式太麻烦,图省事的话,就直接用图表自带的数据集方法解决,比如antV G2:https://g2.antv.antgroup.com/manual/core/data/overview
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container1',
autoFit: true,
height: 500,
});
chart.data(data);
// 关键:把所有指标“长变宽” → “宽变长”,方便 G2 做多系列
chart.scale({
value: { nice: true },
});
chart.tooltip({
shared: true,
showMarkers: true,
});
chart.axis('catid', { title: { text: '栏目ID' } });
chart.axis('value', { title: null });
chart
.line()
.position('catid*value')
.color('metric') // 按指标字段区分颜色/图例
.shape('smooth') // 可选:平滑曲线
.tooltip('metric*value');
// 把宽表转成长表
chart.transform({ type: 'fold',
fields: [
'[求和]views',
'[求和]monthviews',
'[最小值]views',
'[最大值]views',
'[计数]views',
'[去重计数]views',
'[平均值]views',
],
key: 'metric', // 新字段名:指标名称
value: 'value', // 新字段名:指标值
retains: ['catid'],
});
chart.legend('metric', {
position: 'top',
});
chart.render();这样的坏处就是,每次修改,图表都会重新转换一遍数据
echarts 其实更加方便,https://echarts.apache.org/handbook/zh/concepts/dataset/
当然,你也可以不用这样考虑,就是输出为宽表,自己直接手动转换位窄表
参考文章:
什么是窄表?什么是宽表? https://cloud.tencent.com/developer/article/2321715
转载本站文章《数据可视化BI宽表到窄表转换方案探索:如AntV G2 transform.fold 》,
请注明出处:https://www.zhoulujun.cn/html/webfront/visualization/rudiment/9712.html
