Clickhouse是否有可能包含一对转换为列的数组的结果?
形成此结果:
┌─f1──┬f2───────┬f3─────────────┐
│ 'a' │ [1,2,3] │ ['x','y','z'] │
│ 'b' │ [4,5,6] │ ['x','y','z'] │
└─────┴─────────┴───────────────┘
至:
┌─f1──┬x──┬y──┬z──┐
│ 'a' │ 1 │ 2 │ 3 │
│ 'b' │ 4 │ 5 │ 6 │
└─────┴───┴───┴───┘
想法是不必重复每行的标题值。
在我的情况下,“标头”数组f3通过查询唯一并连接到f1,f2。
答案 0 :(得分:2)
您可以借助indexOf
函数来做到这一点。
SELECT *
FROM test_sof
┌─f1─┬─f2──────┬─f3────────────┐
│ a │ [1,2,3] │ ['x','y','z'] │
└────┴─────────┴───────────────┘
┌─f1─┬─f2────────┬─f3────────────────┐
│ c │ [7,8,9,0] │ ['x','y','z','n'] │
└────┴───────────┴───────────────────┘
┌─f1─┬─f2─────────┬─f3────────────────┐
│ d │ [7,8,9,11] │ ['x','y','z','n'] │
└────┴────────────┴───────────────────┘
┌─f1─┬─f2──────┬─f3────────────┐
│ b │ [4,5,6] │ ['x','y','z'] │
└────┴─────────┴───────────────┘
4 rows in set. Elapsed: 0.001 sec.
然后:
SELECT
f1,
f2[indexOf(f3, 'x')] AS x,
f2[indexOf(f3, 'y')] AS y,
f2[indexOf(f3, 'z')] AS z,
f2[indexOf(f3, 'n')] AS n
FROM test_sof
ORDER BY
f1 ASC,
x ASC
┌─f1─┬─x─┬─y─┬─z─┬──n─┐
│ a │ 1 │ 2 │ 3 │ 0 │
│ b │ 4 │ 5 │ 6 │ 0 │
│ c │ 7 │ 8 │ 9 │ 0 │
│ d │ 7 │ 8 │ 9 │ 11 │
└────┴───┴───┴───┴────┘
4 rows in set. Elapsed: 0.002 sec.
请记住当数据数组中不存在标头数组的索引或反之时的情况。
UPD :在不知道“标题”的情况下获取数据的方式。
您将获得三列,第三列带有标题。
SELECT
f1,
f2[num] AS f2_el,
f3[num] AS f3_el
FROM test_sof
ARRAY JOIN arrayEnumerate(f2) AS num
ORDER BY f1 ASC
┌─f1─┬─f2_el─┬─f3_el─┐
│ a │ 1 │ x │
│ a │ 2 │ y │
│ a │ 3 │ z │
│ b │ 4 │ x │
│ b │ 5 │ y │
│ b │ 6 │ z │
│ c │ 7 │ x │
│ c │ 8 │ y │
│ c │ 9 │ z │
│ c │ 0 │ n │
│ d │ 7 │ x │
│ d │ 8 │ y │
│ d │ 9 │ z │
│ d │ 11 │ n │
└────┴───────┴───────┘
14 rows in set. Elapsed: 0.006 sec.
答案 1 :(得分:0)
这是一个有趣的难题。正如已经指出的那样,indexOf()函数似乎是在ClickHouse中旋转数组列的最佳方法,但需要显式选择数组位置。如果您使用的是Python,而结果集不是那么大,则可以通过将数组值翻转到SQL中的行,然后在Python中旋转f2和f3列,以更一般的方式解决问题。运作方式如下。
首先,使用clickHouse-sqlalchemy和pandas将匹配的数组扩展为以下行。 (此示例使用在Anaconda上运行的Jupyter Notebook。)
# Load SQL Alchemy and connect to ClickHouse
from sqlalchemy import create_engine
%load_ext sql
%sql clickhouse://default:@localhost/default
# Use JOIN ARRAY to flip corresponding positions in f2, f3 to rows.
result = %sql select * from f array join f2, f3
df = result.DataFrame()
print(df)
数据框显示如下:
f1 f2 f3
0 a 1 x
1 a 2 y
2 a 3 z
3 b 4 x
4 b 5 y
5 b 6 z
现在,我们可以将f2和f3转换为新的数据帧。
dfp = df.pivot(columns='f3', values='f2', index='f1')
print(dfp)
新数据框dfp出现如下:
f3 x y z
f1
a 1 2 3
b 4 5 6
此解决方案要求您在数据库外部工作,但具有的优点是,只要名称和值匹配,它通常可用于任何一组数组。例如,如果我们添加另一行具有不同的值和属性,则相同的代码将获得正确的答案。这是新的一行。
insert into f values ('c', [7,8,9,10], ['x', 'y', 'aa', 'bb'])
数据透视图框将显示如下。 NaN对应缺失值。
f3 aa bb x y z
f1
a NaN NaN 1.0 2.0 3.0
b NaN NaN 4.0 5.0 6.0
c 9.0 10.0 7.0 8.0 NaN
有关此解决方案的更多信息,请参见https://pandas.pydata.org/pandas-docs/stable/getting_started/dsintro.html和https://github.com/xzkostyan/clickhouse-sqlalchemy。