UNIX/Linux環境でSQLコマンドが使えたらいいのに、と思ったことはありませんか?私はあります。
10万〜100万行レベルのデータを集計したいけど、わざわざDBにぶっ込むほどではない。そんな時は、awk, join, grep, paste, wc, uniqなどなどの各種コマンドを駆使して集計しています。
ちなみに、joinコマンドに関してはここに大変お世話になりました。本当に便利すぎて生きるのが辛いです。
joinコマンドが便利過ぎて生きるのが辛い - Y's note
Linuxシステムプログラミング作者: Robert Love,ロバートラブ,千住治郎出版社/メーカー: オライリージャパン発売日: 2008/04/16メディア: 大型本購入: 5人 クリック: 181回この商品を含むブログ (29件) を見る 結合 Unix/Linuxの標準コマンドで2つのファイルの共通keyで連結することができます。共通keyでの結合にはjoinコマンドを利用します。joinによりSQLのinner joinに近いことがコマンドだけで出来てしまいます。今までテキスト処理をコマンドで行う事が少なかったのでjoinの活用方法を知りませんでしたが、今回調べた内容を記録します。...
d.hatena.ne.jp
ただ、これが複数ファイルにまたがって処理をしたりして、複雑になってくるとだんだん何のデータを操っているか混乱してきます。そんなときに、カジュアルにtsv, csvファイルに対してqueryを投げられたらいいのになぁと感じていました。
そんなときに、これを見つけました。
harelba/q
q is a command line tool that allows direct execution of SQL-like queries on CSVs/TSVs (and any other tabular text files). q treats ordinary files as database tables, and supports all SQL constructs, such as WHERE, GROUP BY, JOIN s, etc. It supports automatic column name and type detection, and q provides full support for multiple character encodings.
github.com
q という超絶短いコマンドのため、単語のググラビリティ(単語のググられやすさ/ググりやすさ。)が悪すぎて、あまり発見されないかもしれません。
俺が求めていたのはコレだぁ!ということで、実務でも使っています。
もっと普及して欲しいので、インストール手順からちょっとした実行サンプルを紹介します。
久々に見てみたら、brewでインストールできるようになってました。下記インストール手順参照のこと。(2015/07/24 追記)http://harelba.github.io/q/install.html
必要環境はPython 2.5以上か、SQLite3モジュールがインストールされているPython 2.4以上です。(Python 2.5は、SQLite3が標準バンドルされています)
% mkdir -p ~/local/bin
% git clone git@github.com:harelba/q.git
Cloning into q…
remote: Reusing existing pack: 145, done.
remote: Counting objects: 16, done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 161 (delta 7), reused 8 (delta 0)
Receiving objects: 100% (161/161), 52.47 KiB, done.
Resolving deltas: 100% (60/60), done.中身を見てみると、1行目にインタプリタの指定があります。
自分の環境は、2.4.3と2.7.1の両バージョンがインストールしてあるため、2.7.1で実行されるように変更します。
% ~/local/bin/q/q -v
q version 1.1.2動きました。
PATHを通します。
.zshrcに以下を追記。
export PATH=$PATH:/home/serima/local/bin/q
パスが通りました!
Examplesが載っているので、試しにそのまま入力してみます。
% seq 1 1000 | q "select avg(c1),sum(c1) from -"
500.5 500500おー!素晴らしい。
% seq 1 1000で12345(略)1000
を出力して、これを標準入力として q に渡す。c1というのが、カラムの1番目という意味なので、avg(c1)で、1〜1000の総和の平均sum(c1)で、1〜1000の総和が出力されています。
こんな風にgroup byも使える!
% cat test.txt
Mike 10
John 1
Bob 8
Mary 19
Bob 15
Bob 20
Mike 2
% q "select c1, count(*), sum(c2) from test.txt group by c1"
Bob 3 43
John 1 1
Mary 1 19
Mike 2 12ちなみに awk でやろうとするとこうですか。
% awk ’{a[$1]++;b[$1]=b[$1]+$2}END{for (i in a) printf("%s %d %dn", i, a[i], b[i])}’ test.txt
Mike 2 12
Bob 3 43
Mary 1 19
John 1 1join も書けます。
% cat test1.txt
a1234 aa1
b1234 aa2
c1234 aa3
d1234 aa3
% cat test2.txt
1 a1234 bb1
2 a1234 bb2
3 b1234 cc1
4 c1234 dd3
5 e1234 NULL
% q "select * from test1.txt as a left join test2.txt as b on a.c1 = b.c2"
a1234 aa1 1 a1234 bb1
a1234 aa1 2 a1234 bb2
b1234 aa2 3 b1234 cc1
c1234 aa3 4 c1234 dd3
d1234 aa3SQLに馴染みのある人はqを使ったほうがサクッと書けていいですね。