> 技术文档 > 在kdb+x中使用SQL

在kdb+x中使用SQL

kdb+x是Kx Systems公司新发布的产品,它对SQL的支持分为两方面,一是通过q命令行工具执行,二是通过在Python中执行。

一、获取并安装kdb+x
登录https://kdb-x.kx.com/sign-in,填写电子邮件地址,就能登录获取下载地址,也可以在线安装,页面上提供许可码,同时也会发邮件。

我使用下载安装方式,安装包地址就不贴出来了,因为地址是动态的,和登录用户的会话绑定。

离线安装命令行为

unzip l64arm-bundle.zip && bash install_kdb.sh --offline --b64lic BASE64许可码

注意这里有个问题。进行到验证安装阶段,安装脚本提示

-------- Verifying installation --------Error: Installation verification failed: q binary missing or not executable-------- Installation failed - Rolling back changes --------

然后就恢复到未安装状态了。
解决这个问题的办法是用文本编辑器打开install_kdb.sh,从中找到verify_installation || perform_rollback一行,把它删除或注释掉,即

 # verify_installation || perform_rollback

然后重新执行离线安装命令行,就能安装完成。安装位置在/用户home目录/.kx/bin:$PATH

如果需要在任意目录执行,将它加入搜索路径,例如

export PATH=\"/root/.kx/bin:$PATH\"

还建议安装rlwrap,然后将下面行加入用户配置脚本

alias q=\"rlwrap -r q

二、在q命令行执行SQL语句
输入q,就进去交互命令行界面,提示符是q),q命令可直接输入,比如

til(10)输出0 1 2 3 4 5 6 7 8 9

要执行SQL,只要在相应的语句前加s)前缀。比如:(注意这里q)是提示符,不需要用户输入)

建表q)s)CREATE TABLE tripsFare (vendor varchar,fare float)`tripsFare插入2行q)s)INSERT INTO tripsFare(vendor,fare) values (\'CMT\',100),(\'didi\',200)查询q)s)select * from tripsFare vendor fare-----------CMT 100 didi 200 

kdb+x具体支持的SQL类型参考文档

三、在python命令行执行SQL语句
首先安装python包pykx,命令行如下

python3 /par/pip.pyz install --pre pykx --break-system-packages -i https://pypi.tuna.tsinghua.edu.cn/simple

我是因为docker环境安装pip太麻烦,就用了pip.pyz,访问pypi网站很慢,就用了清华源镜像。如果你的环境有pip,访问pypi网站也很快,那么,

pip install --pre pykx

即可。
安装完成后,下载教学包,里面有python做时间序列分析的示例,也提到了SQL写法,摘录如下。
先把stocks.csv解压缩到/par。

>>> import pykx as kx>>> kx.q.til(10)pykx.LongVector(pykx.q(\'0 1 2 3 4 5 6 7 8 9\'))>>> from datetime import date>>> import numpy as np>>> import os>>> import psutilTraceback (most recent call last): File \"\", line 1, in <module>ModuleNotFoundError: No module named \'psutil\'>>> from pathlib import Path>>> with open(\'/par/stocks.txt\', \'r\') as f:... py_symbols = f.read().split(\'\\n\')... >>> syms = kx.random.random(100, py_symbols)>>> n = 20000000;>>> day = date(2025, 1, 1);>>> trade = kx.Table(data = {... \'time\': day + kx.random.random(n, kx.q(\'24:00:00\')),... \'sym\': kx.random.random(n, syms),... \'price\': kx.random.random(n, 100.0),... \'size\': kx.random.random(n, 1000)... }... ).sort_values(\'time\')>>> trade.dtypespykx.Table(pykx.q(\'columns datatypes --------------------------time \"kx.TimestampAtom\"sym \"kx.SymbolAtom\" price \"kx.FloatAtom\" size \"kx.LongAtom\" \'))生成了2000万行>>> len(trade)20000000>>> trade.head(10)pykx.Table(pykx.q(\'time sym price size-------------------------------------------------2025.01.01D00:00:00.000000000 SAVA 86.12543 644 2025.01.01D00:00:00.000000000 JAMF 16.51214 828 2025.01.01D00:00:00.000000000 TBBK 10.68305 327 2025.01.01D00:00:00.000000000 WVVIP 89.58529 990 2025.01.01D00:00:00.000000000 LGCL 38.29104 904 2025.01.01D00:00:00.000000000 MNST 40.16916 264 2025.01.01D00:00:00.000000000 DSWL 70.14543 633 2025.01.01D00:00:00.000000000 APCX 32.23879 629 2025.01.01D00:00:00.000000000 KPLT 18.70299 276 2025.01.01D00:00:00.000000000 SOXQ 51.78228 408 \'))下面是等价SQL语句>>> kx.q.sql(\"SELECT * FROM $1 LIMIT 10\", trade)pykx.Table(pykx.q(\'time sym price size-------------------------------------------------2025.01.01D00:00:00.000000000 SAVA 86.12543 644 2025.01.01D00:00:00.000000000 JAMF 16.51214 828 2025.01.01D00:00:00.000000000 TBBK 10.68305 327 2025.01.01D00:00:00.000000000 WVVIP 89.58529 990 2025.01.01D00:00:00.000000000 LGCL 38.29104 904 2025.01.01D00:00:00.000000000 MNST 40.16916 264 2025.01.01D00:00:00.000000000 DSWL 70.14543 633 2025.01.01D00:00:00.000000000 APCX 32.23879 629 2025.01.01D00:00:00.000000000 KPLT 18.70299 276 2025.01.01D00:00:00.000000000 SOXQ 51.78228 408 \'))

注意上述sql,表名用$1代替,然后trade是实际的pykx表名。其他值也可以用变量占位符替换。比如

>>> kx.q.sql(\"SELECT * FROM $1 where price < $2 LIMIT 2\", trade,50)pykx.Table(pykx.q(\'time sym price size-------------------------------------------------2025.01.01D00:00:00.000000000 JAMF 16.51214 828 2025.01.01D00:00:00.000000000 TBBK 10.68305 327 \'))