[英]Return clickhouse array as column
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。
您可以借助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.
這是一個有趣的難題。 正如已經指出的那樣,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 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.