clickhouse--行列转换

本文详细介绍了如何在ClickHouse中通过unionall和arrayjoin实现数据的列转行操作,以及使用map和sumIf函数对数据进行按地区汇总。通过实例展示了如何从test_transfer表中按pkg分组,分别统计每个地区的数值并转化为行格式。

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


列转行

数据准备

创建一张数据表,如下所示:

create table test.test_transfer(
	pkg String,
	day String,
	region_0 UInt32,
	region_1 UInt32,
	region_2 UInt32
) ENGINE = MergeTree()
partition by day
ORDER BY pkg

插入数据:

INSERT INTO test.test_transfer VALUES
('pkg1', '20220510', 1000, 2000, 3000),
('pkg1', '20220511', 1000, 2000, 3000),
('pkg1', '20220512', 1000, 2000, 3000),
('pkg1', '20220513', 1000, 2000, 3000),
('pkg1', '20220411', 1000, 2000, 3000),
('pkg1', '20220412', 1000, 2000, 3000),
('pkg2', '20220510', 1000, 2000, 3000),
('pkg2', '20220511', 2000, 3000, 3000),
('pkg2', '20220512', 1000, 3000, 3000),
('pkg2', '20220513', 3000, 2000, 3000)

查询结果可以得到:

SELECT *
FROM test.test_transfer
FORMAT PrettyCompactMonoBlock
┌─pkg──┬─day──────┬─region_0─┬─region_1─┬─region_2─┐
│ pkg1 │ 20220513 │     1000 │     2000 │     3000 │
│ pkg2 │ 20220513 │     3000 │     2000 │     3000 │
│ pkg1 │ 20220412 │     1000 │     2000 │     3000 │
│ pkg1 │ 20220512 │     1000 │     2000 │     3000 │
│ pkg2 │ 20220512 │     1000 │     3000 │     3000 │
│ pkg1 │ 20220510 │     1000 │     2000 │     3000 │
│ pkg2 │ 20220510 │     1000 │     2000 │     3000 │
│ pkg1 │ 20220411 │     1000 │     2000 │     3000 │
│ pkg1 │ 20220511 │     1000 │     2000 │     3000 │
│ pkg2 │ 20220511 │     2000 │     3000 │     3000 │
└──────┴──────────┴──────────┴──────────┴──────────┘

数据需求

需要按照pkg列求其按照不同区间的数值。

union all实现

select 
	pkg,
	'region0' as region,
	sum(region_0) as value
from test.test_transfer
group by pkg
union all
select 
	pkg,
	'region1' as region,
	sum(region_1) as value
from test.test_transfer
group by pkg
union all
select 
	pkg,
	'region2' as region,
	sum(region_2) as value
from test.test_transfer
group by pkg
FORMAT PrettyCompactMonoBlock;

结果如下:

┌─pkg──┬─region──┬─value─┐
│ pkg1 │ region0 │  6000 │
│ pkg2 │ region0 │  7000 │
│ pkg1 │ region2 │ 18000 │
│ pkg2 │ region2 │ 12000 │
│ pkg1 │ region1 │ 12000 │
│ pkg2 │ region1 │ 10000 │
└──────┴─────────┴───────┘

arary join

采用这种方式话,首先我们要将每个区间的统计值算出来,然后将不同区间结果压缩得到一个数组,代码如下:

select
	pkg,
	array(region_0, region_1, region_2) as value_arr
from
	(select 
		pkg,
		sum(region_0) as region_0,
		sum(region_1) as region_1,
		sum(region_2) as region_2
	from test.test_transfer
	group by pkg
	) aa
FORMAT PrettyCompactMonoBlock;

查询的结果如下:

┌─pkg──┬─value_arr──────────┐
│ pkg1 │ [6000,12000,18000] │
│ pkg2 │ [7000,10000,12000] │
└──────┴────────────────────┘

那么得到数组之后呢,我们就可以使用array join的方法对数组进行展开了,代码如下:

select
	pkg,
	region,
	value
from
	(select
		pkg,
		array(region_0, region_1, region_2) as value_arr
	from
		(select 
			pkg,
			sum(region_0) as region_0,
			sum(region_1) as region_1,
			sum(region_2) as region_2
		from test.test_transfer
		group by pkg
		) aa
	) bb
array join
	['region_0', 'region_1', 'region_2'] as region,
	value_arr as value
FORMAT PrettyCompactMonoBlock;

得到结果如下:

┌─pkg──┬─region───┬─value─┐
│ pkg1 │ region_0 │  6000 │
│ pkg1 │ region_1 │ 12000 │
│ pkg1 │ region_2 │ 18000 │
│ pkg2 │ region_0 │  7000 │
│ pkg2 │ region_1 │ 10000 │
│ pkg2 │ region_2 │ 12000 │
└──────┴──────────┴───────┘

行转列

数据准备

创建一张数据表,如下所示:

create table test.test_transfer2(
	pkg String,
	region String,
	value UInt32
) ENGINE = MergeTree()
ORDER BY pkg

插入数据:

INSERT INTO test.test_transfer2 VALUES
('pkg1', 'region_0', 3000),
('pkg1', 'region_0', 3000),
('pkg1', 'region_1', 12000),
('pkg1', 'region_2', 8000),
('pkg1', 'region_2', 6000),
('pkg1', 'region_2', 4000),
('pkg2', 'region_0', 7000),
('pkg2', 'region_1', 10000),
('pkg2', 'region_2', 12000)

查询结果可以得到:

SELECT *
FROM test.test_transfer2
┌─pkg──┬─region───┬─value─┐
│ pkg1 │ region_0 │  3000 │
│ pkg1 │ region_0 │  3000 │
│ pkg1 │ region_1 │ 12000 │
│ pkg1 │ region_2 │  8000 │
│ pkg1 │ region_2 │  6000 │
│ pkg1 │ region_2 │  4000 │
│ pkg2 │ region_0 │  7000 │
│ pkg2 │ region_1 │ 10000 │
│ pkg2 │ region_2 │ 12000 │
└──────┴──────────┴───────┘

数据需求

将region列的数据按照值转为不同的列,并将对应的value值统计之后填进去。

map

clickhouse中的map方法可以实现类似pivot的功能,如下所示:

WITH CAST(sumMap([region], [value]), 'Map(String, UInt32)') AS map
select 
	pkg,
	map['region_0'] AS region_0,
    map['region_1'] AS region_1,
    map['region_2'] AS region_2
from test.test_transfer2
group by pkg

结果如下所示:

┌─pkg──┬─region_0─┬─region_1─┬─region_2─┐
│ pkg1 │     6000 │    12000 │    18000 │
│ pkg2 │     7000 │    10000 │    12000 │
└──────┴──────────┴──────────┴──────────┘

sumIf

也可以使用clickhouse中的sumIf函数进行条件求和,并命名为指定的列,如下:

select
	pkg,
	sumIf(value, region = 'region_0') AS region_0, 
    sumIf(value, region = 'region_1') AS region_1, 
    sumIf(value, region = 'region_2') AS region_2
from test.test_transfer2
group by pkg

结果如下:

┌─pkg──┬─region_0─┬─region_1─┬─region_2─┐
│ pkg1 │     6000 │    12000 │    18000 │
│ pkg2 │     7000 │    10000 │    12000 │
└──────┴──────────┴──────────┴──────────┘

参考资料

如何在 ClickHouse 中实现行列转换
clickhouse pivot / unpivot

### 解决PyCharm无法加载Conda虚拟环境的方法 #### 配置设置 为了使 PyCharm 能够成功识别并使用 Conda 创建的虚拟环境,需确保 Anaconda 的路径已正确添加至系统的环境变量中[^1]。这一步骤至关重要,因为只有当 Python 解释器及其关联工具被加入 PATH 后,IDE 才能顺利找到它们。 对于 Windows 用户而言,在安装 Anaconda 时,默认情况下会询问是否将它添加到系统路径里;如果当时选择了否,则现在应该手动完成此操作。具体做法是在“高级系统设置”的“环境变量”选项内编辑 `Path` 变量,追加 Anaconda 安装目录下的 Scripts 文件夹位置。 另外,建议每次新建项目前都通过命令行先激活目标 conda env: ```bash conda activate myenvname ``` 接着再启动 IDE 进入工作区,这样有助于减少兼容性方面的问题发生概率。 #### 常见错误及修复方法 ##### 错误一:未发现任何解释器 症状表现为打开 PyCharm 新建工程向导页面找不到由 Conda 构建出来的 interpreter 列表项。此时应前往 Preferences/Settings -> Project:...->Python Interpreter 下方点击齿轮图标选择 Add...按钮来指定自定义的位置。按照提示浏览定位到对应版本 python.exe 的绝对地址即可解决问题。 ##### 错误二:权限不足导致 DLL 加载失败 有时即使指定了正确的解释器路径,仍可能遇到由于缺乏适当的操作系统级许可而引发的功能缺失现象。特别是涉及到调用某些特定类型的动态链接库 (Dynamic Link Library, .dll) 时尤为明显。因此拥有管理员身份执行相关动作显得尤为重要——无论是从终端还是图形界面触发创建新 venv 流程均如此处理能够有效规避此类隐患。 ##### 错误三:网络连接异常引起依赖下载超时 部分开发者反馈过因网速慢或者其他因素造成 pip install 操作中途断开进而影响整个项目的初始化进度条卡住的情况。对此可尝试调整镜像源加速获取速度或是离线模式预先准备好所需资源包后再继续后续步骤。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值