プログラミング言語とデータベースQ:構文は企業では役割を果たしません

モバイルの新しい料金プランを選択する必要がありました。 excelとgoogle-docsで約30分を費やすと、これから賢明なことは何もできず、dbなしではできないことが明らかになりました。



少し考えてみると、手とそれ自体が「q」と入力しました。これは、現在、コンピューターで使用できる唯一のものでした。 彼が彼について知っていたのは、ファイルの解析と検索という簡単なタスクのために、彼が1年前と最後に約30分間起動したことです。



その後、多くのq、すなわちascii、APL言語とSchemeのサブセットのフォロワー、すなわちkとその拡張k-sqlがあり、 Qという名前の製品に縮退します-言語とそれに組み込まれたデータベースの緊密な接続。



C:\Users\unknown\Dropbox\j>q KDB+ 3.0 2013.02.06 Copyright (C) 1993-2013 Kx Systems w32/ 2()core 2972MB unknown win-d2om7les24v 192.168.1.2 PLAY 2013.05.07
      
      









ちょっとした歌詞:オペレーターのサイトからレポートをcsvでダウンロードし、タイトルを少し調整します。

 ; ;tel;time;-; ;money; ;    ;22.02.2013 20:38:14;79064014328;00:00:13;0;114,9175;0,0000;114,9175;  ;22.02.2013 20:03:49;79094445182;00:12:05;0;114,9175;0,0000;114,9175;    ;22.02.2013 17:04:39;79064014328;00:01:15;0;115,8175;-0,9000;114,9175;    ;22.02.2013 13:18:22;79064014328;00:01:36;0;116,7175;-0,9000;115,8175;    ;22.02.2013 01:35:00;;00:00:00;0;119,3675;-2,6500;116,7175;  ;21.02.2013 23:40:42;*102;00:00:01;0;119,3675;0,0000;119,3675;
      
      







次に、マニュアルを読み、テキストファイル0:を読み取ります並行して、左側に列の形式と区切り文字を指定することでファイルをフィールドに分割できます区切り文字がリストの場合、テーブルの列は最初の行から名前が付けられます。 必要なフィールドのみを2回選択すると、テーブルの準備ができました。



データの準備について読んで退屈している人は、 データ分析にすぐに飛び込むことができます



 q)clog:select tel,time,money from ("SSSTSSSS";enlist ";") 0: `:tel.txt q)clog tel time money --------------------------------- 79064014328 00:00:31.000 0,0000 79263883922 00:02:06.000 0,0000 79064014328 00:01:15.000 -0,9000 79064014328 00:01:36.000 -0,9000 00:00:00.000 -2,6500 *102 00:00:01.000 0,0000 ..
      
      





qはベクトルデータベースであるため、基本的にclogは辞書であり、列名は値のリストです。



 q)clog.money `0,0000`0,0000`-0,9000`-0,9000`-2,6500`0,0000`0,0000`0,0000`0,0000`0,0000`-0,..
      
      





データを少し準備します。 お金は数値形式ではないことがわかります。数値に変換する必要があります。ssrはオラクルの代替品です。 $(キャスト)という用語は、さまざまな変換と型変換を扱います。この場合、文字列から数値を読み取ります。



それぞれが地図です



 {"F"$ssr[string x;",";"."]} each clog.money
      
      





さて、更新を使用してすべてをテーブルに書き留めます。 小さな機能があります。 clogテーブル名を使用すると、更新機能の結果は、更新された値を持つ新しいテーブルになります。 ただし、テーブル名を「clog」と指定すると、変更が保存されます。 また、電話を文字列にします。最初は「S」は文字列ではなく、文字タイプです。



 q)update string tel, {"F"$ssr[string x;",";"."]} each money from `clog `clog
      
      





このq-sqlのほとんどすべての単語は、わずかな構文糖を持つ通常の関数です。 たとえば、ビット文字列をインデックスのリストに単純に変換する場合など、個別に使用できます。



比較はリストで機能します。 結果はビット文字列であり、そこからインデックスを抽出し、これらのインデックスから選択すると、対応するリスト項目がテーブルから抽出されます。

 q)15<40 10 20 30 1011b q)where 15<40 10 20 30 0 2 3
      
      





ファイルには、着信と発信の両方の呼び出しと異なるサービスの支払いが含まれています。お金が引き落とされた行を選択し、電話番号があり、この古い名前を割り当てます。



 q)clog:select from clog where money<0,not tel like "" q)clog tel time money -------------------------------- "79064014328" 00:01:15.000 -0.9 "79064014328" 00:01:36.000 -0.9 "79064014328" 00:01:33.000 -0.9 "79104652109" 00:01:23.000 -11.9 "79265996349" 00:00:12.000 -5.95 ..
      
      





その後、オペレーターによって分類するために使用されるコードを決定します。



少し後に、コード抽出を関数に取り込む必要があることに気付きました。



 q)gcode:1_ 4# / get code from tel q)gcode each clog.tel "906" "906" "906" "910" "926" ..
      
      





 q)distinct gcode each clog.tel "906" "910" "926" ..
      
      





execを使用した、よりSQLに似たエントリを次に示します。 execは同じselectですが、テーブルの辞書を返さず、クエリまたはテーブルの結果の値または値を返します。



 q)codes:exec distinct gcode each tel from clog q)codes "906" "910" "926" ..
      
      





次に、辞書に移動します。それらは単に<keys>と説明されています! <値>。 辞書コード<>演算子を作成します。



 q)ops:codes ! `beeline`mts`megafon`beeline`mts`beeline`beeline`mts`moscow q)ops "906"| beeline "910"| mts "926"| megafon "909"| beeline "495"| moscow ..
      
      





多くの関税は1分で一杯に切り上げられますが、便宜上、フィールドに入力します。 テーブルに保存せず、結果を取得するだけです。後でこのフィールドを使用してビューを作成するからです。 ミリ秒単位の時間なので、1000で割ります。



 q)update ctime:ceiling (time%1000)%60 from clog tel time money ctime -------------------------------------- "79064014328" 00:01:15.000 -0.9 2 "79064014328" 00:01:36.000 -0.9 2 "79064014328" 00:01:33.000 -0.9 2 "79104652109" 00:01:23.000 -11.9 2 "79265996349" 00:00:12.000 -5.95 1 ..
      
      





tを書いた場合、演算子と数分でビューを作成します。テーブルtを作成します。 更新により元の列が保存されることを思い出してください。



 q)t::update op:ops@gcode each tel, ctime:ceiling (time%1000)%60 from clog q)t tel time money op ctime ---------------------------------------------- "79064014328" 00:01:15.000 -0.9 beeline 2 "79064014328" 00:01:36.000 -0.9 beeline 2 "79064014328" 00:01:33.000 -0.9 beeline 2 "79104652109" 00:01:23.000 -11.9 mts 2 "79265996349" 00:00:12.000 -5.95 megafon 1 ..
      
      





必要なものをすべて入力しました。念のためにtの結果をファイルに保存します。もちろん、下駄とview`tの説明を保存する方が正確です。

 q)save `:t `:t
      
      







上記のすべては単なるデータの準備であり、もう少し興味深い:解析します。







誰が最も多く電話をかけたかを見てみましょう、それからグループが始まります。 グループ化は、各キーエントリのリストを作成するselect関数のパラメーターです。



 q)select ctime by tel from t tel | ctime .. -------------| --------------------------------------------------------------.. "74956471602"| ,1 .. "79031398210"| 7 3 .. "7903X" | ,2 .. "79064014328"| 2 2 2 2 1 2 1 1 1 3 1 2 2 3 1 1 1 1 2 2 3 3 3 1 3 2 1 1 0 2 1 .. ..
      
      





次に、このリストの形式のパラメータで関数を実行します。descは逆ソート関数です。通常のリストとテーブルの両方をソートします。デフォルトでは、最後の列でソートされます。



 q)desc select sum ctime by tel from t tel | ctime -------------| ----- "79064014328"| 126 "79094445182"| 36 "79652650530"| 30 ..
      
      





1つの番号に多くの呼び出しがあったことに気付いて、「お気に入り番号」列を追加し、少し後にオペレーターのフィールドでこれを単純に示すことにし、古いビューに新しい名前を割り当て、「t」は古いビューに基づいた新しいビューになりました:



 q)t2::update op:ops@gcode each tel, ctime:ceiling (time%1000)%60 from clog q)t::update op:`lub from t2 where tel like "79064014328" q)t tel time money op ctime ---------------------------------------------- "79064014328" 00:01:15.000 -0.9 lub 2 "79064014328" 00:01:36.000 -0.9 lub 2 "79064014328" 00:01:33.000 -0.9 lub 2 "79104652109" 00:01:23.000 -11.9 mts 2 "79265996349" 00:00:12.000 -5.95 megafon 1 ..
      
      





今、お金、特にメガホンの関税について考える時です。



そこには3つのコペックがあり、機能を簡単に説明できます。



 q)meg3:{0.03*sum x}
      
      





各オペレーターのお金が何であるかを見てみましょう:

 q)select meg3 time%1000 by op from t op | time -------| ------ beeline| 111.93 lub | 148.05 megafon| 29.1 moscow | 0.93 mts | 24.45
      
      





関税オプションを入力する必要があります。数値が「lub」の場合、価格を2で割って30pを加算します。

 q)lub:{$[x=`lub;30+y%2;y]} / [op;time]
      
      







それだけです。計算する関数は次のようになります。ここではlubはカリー化を使用します。

 q){lub[x] meg3[y]}
      
      







残念ながら、キーと「by」結果の値を関数に渡す方法が見つからなかったため、これをサブクエリとしてフォーマットします。 opとtimeは通常のdbのようにテーブルの行の2つの値ではないため、リスト全体(この場合はリストとリストのリスト)が関数に転送されますが、上記の関数は2つのパラメーターのみを想定しています:演算子そして、時間のリストなので、それぞれの関数を使用します。これは、 '(引用符)で示され、基本的にzipWithですが、リストの数を制限することはありません。 通常のdbとは異なり、リクエストは ':によってのみ複雑になります。



 q)select money:{lub[x] meg3[y]}'[op;time] from select time%1000 by op from t money ------ 259.98 29.1 0.93 24.45
      
      





要約すると、ここではexec sumとsum execの両方を書くことができます-結果はexecを合計するか、execは結果を合計します-役割を果たしません:



 q)exec sum {lub[x] meg3[y]}'[op;time] from select time%1000 by op from t 314.46
      
      





この関税への切り替えにいくら費やすかは明らかです。 今度は、分が丸められ、次に秒が計算される別のものを計算してみましょう。 指定された時間ごとにカウントする必要があります。



 q)mego:sum {1.20+$[x<=60;0;1.20*(x-60)%60]} each q)exec sum {lub[x] mego[y]}'[op;time] from select time%1000 by op from t 258.06
      
      





完全なコード:



 clog:select tel,time,money from ("SSSTSSSS";enlist ";") 0: `:tel.txt {"F"$ssr[string x;",";"."]} each clog.money update string tel, {"F"$ssr[string x;",";"."]} each money from `clog clog:select from clog where money<0,not tel like "" gcode:1_ 4# codes:exec distinct gcode each tel from clog ops:codes ! `beeline`mts`megafon`beeline`mts`beeline`beeline`mts`moscow t2::update op:ops@gcode each tel, ctime:ceiling (time%1000)%60 from clog t::update op:`lub from t2 where tel like "79064014328" meg3:{0.03*sum x} mego:sum {1.20+$[x<=60;0;1.20*(x-60)%60]} each lub:{$[x=`lub;30+y%2;y]} exec sum {lub[x] meg3[y]}'[op;time] from select time%1000 by op from t exec sum {lub[x] mego[y]}'[op;time] from select time%1000 by op from t
      
      





このテキストを作成することは、これらの14行を書くよりもはるかに困難でした。 他のデータベースには不可能なものはないことは明らかですが、使いやすさといくつかの構造を書くことの自明性は、私がこれを書くのに役立ちました。 当初は、通常のsqlから切り替えるのは少し困難でしたが、ここのテーブルはリストにデータを格納し、原則として、ほとんどすべての組み込みデータ型で機能することを認識した後、はるかに明確になりました。 このdbの慣用的なシンプルさと実装の容易さであり、実際、このツールを効果的に使用できるのはスキームとAPLの混合です。 この印象は、APLと機能であり、SQLとデータベースに移行しました。



データベース全体は、サイズが最大400 KBの1つのq.exeファイルで構成されます。 懐疑論者はその後微笑むでしょうが、この製品の顧客リストhttp://kx.com/end-user-customers.phpを見てください

http://kx.com/software-download.phpからダウンロードして、これで遊ぶことができます



All Articles