log

日記です

GROUP BY後、最小・最大の値を抽出する

地味に調べたのでメモ。

こたえ
SELECT
  m1.item_id,
  m1.price,
  m1.sale_price
FROM
  items m1,
  items m2
GROUP BY
  m1.item_id, m1.price, m1.sale_price, m2.category_id
HAVING
  MIN(m2.sale_price) = m1.sale_price;
サンプルテーブル作成
CREATE TABLE `items` (
  `category_id` int(11) DEFAULT NULL,
  `item_id` int(11) DEFAULT NULL,
  `price` double DEFAULT NULL,
  `sale_price` double DEFAULT NULL
);

INSERT INTO items VALUES(1, 1, 300, 150);
INSERT INTO items VALUES(1, 2, 200, 100);
INSERT INTO items VALUES(1, 3, 150, 110);
INSERT INTO items VALUES(2, 4, 1300, 1150);
INSERT INTO items VALUES(2, 5, 1200, 1100);
INSERT INTO items VALUES(2, 6, 1150, 1110);
サンプルテーブル確認
mysql> SELECT * FROM items;
+-------------+---------+-------+------------+
| category_id | item_id | price | sale_price |
+-------------+---------+-------+------------+
|           1 |       1 |   300 |        150 |
|           1 |       2 |   200 |        100 |
|           1 |       3 |   150 |        110 |
|           2 |       4 |  1300 |       1150 |
|           2 |       5 |  1200 |       1100 |
|           2 |       6 |  1150 |       1110 |
+-------------+---------+-------+------------+
6 rows in set (0.00 sec)
実行
mysql> SELECT
    ->   m1.item_id,
    ->   m1.price,
    ->   m1.sale_price
    -> FROM
    ->   items m1,
    ->   items m2
    -> GROUP BY
    ->   m1.item_id, m1.price, m1.sale_price, m2.category_id
    -> HAVING
    ->   MIN(m2.sale_price) = m1.sale_price;
+---------+-------+------------+
| item_id | price | sale_price |
+---------+-------+------------+
|       2 |   200 |        100 |
|       5 |  1200 |       1100 |
+---------+-------+------------+
2 rows in set (0.00 sec)

追記

うーん、、、なんかデータが多いと微妙な気がしたのでプログラム側で集計するようにしました。MySQLにもRANK関数があればいいんですけどねぇ

料理

f:id:ariteku:20160910223954j:plain
最近料理が捗ってる

久々にいい時間を過ごした気がする

職場にも弁当持参が増えた
次は何を作ろうかなぁ

re:dashをアップデートした

所感

fabricでスクリプトが用意されていて、かなり簡単にアップデートできた。
アップデート時にはデータのマイグレーションが必要な場合がある。

事前準備

# fabric install
sudo pip install fabric requests

# fabric code download
wget https://gist.githubusercontent.com/arikfr/440d1403b4aeb76ebaf8/raw/ea1e3955f660b4448db7af8f69dc27ac0993abfd/fabfile.py

手順(コマンド実行)

# 最新アップデート
# Apply new migrations? (make sure you have backup) [Y/n] と聞かれるので Yes と答える
# Noと答えると旧バージョンのQueriesやDashboardが表示されなくなる
fab -H ${HOST} -u ubuntu -i ~/.ssh/unisize-server.pem deploy_latest_release

# ダウングレード
fab -H ${HOST} -u ubuntu -i ~/.ssh/unisize-server.pem link_to_current:version_name=redash.0.10.1.b1834

# Restart
fab -H ${HOST} -u ubuntu -i ~/.ssh/unisize-server.pem restart_services

終わり

整備されてていい!

re:dash運用開始

エンジニア⇔ビジネス間で「こういうデータみたいです〜」「ユーザー数が〜」みたいなの、どこの現場に行ってもあると思うんですが、毎回クエリ発行してCSVに整形してExcelで開けるように文字コード変えて・・・と何かと作業になりがちです。自作ツールや管理画面作ってもいいんですが、ソリューションでさくっと解決できた。


クエリ作って、re:dashに貼り付けて、軽く可視化(今のとこpivot使うことが多い)して「どーぞ」と渡せる。次回からはここ見てくださいと。


便利!


今のところちゃんとワークしそうな印象。

レンタルサーバーでGolangを使うとき

hetemlなど、基本PHP前提のレンタルサーバーgolangを動かしたくなってしまった時に気をつけるべき知見を得た。(そもそもPHPで書けよ、って話だが)

おまとめ(困ったこと)

  • そもそもデーモンを動かせないので、net/httpを使った常駐型のhttpサーバーは実行できない。
    • バックグラウンド実行できると見せかけ、ログアウトし一定時間経つと消えている。
    • mod_rewritelocalhost:8080のgolangへリバースプロキシするという荒業を試し、リクエストが通ることは確認できたが安定稼働できないため諦めた。
    • もしかするとできないこともないかもしれないが、流石に力技すぎる。(supervisord入れようかとかしたけど筋が悪い臭いがプンプン。phpで書きなおそうか考え始める。)
  • golangでもcgiが作れるので、cgiを作ってそれを呼び出す。
  • cronでgolangのバッチを動かしたくなったら、実行スレッド数に気をつける。runtime.GOMAXPROCS()で制御可能。

golangCGI

net/http/cgi パッケージにcgiを作るためのライブラリがあるのでこれを使用する。
POST/GET パラメーターやCookie、Header等を使用することが可能。
ぼくは普段gin等のframework使っているのであれだが、net/httpでゴリゴリサーバー書いている人なら違和感なく作ることができるんだと思う。

プロセス制限注意

共有サーバーって制限が強い><

ulimit -u
15

たったの15・・・goroutineを使うと一発で死にます。

runtime.GOMAXPROCS(1)

などでスレッド数1に変更。

sqlのopen connectionも一応減らしておいた

db, err := sql.Open(conf.Driver, conf.Dsn)
db.SetMaxIdleConns(1)
db.SetMaxOpenConns(1)

AWSとかVPSとか自由な世界で生きているとレンサバ辛い。
CGIってまあアリだなぁと思った。Apache + PHP or CGIしか動かせないようなところでは。
意外と戦える!

車で京都・大阪旅行

水曜の深夜に出発し、土曜日の深夜に帰宅開始
関東発で行き12時間、帰り7時間半
高速代+ガソリン代で一人10400円ぐらいで済んだ。
宿泊はゲストハウス2700円(すごく腰の低い方だった)、二日目は友人宅
京都で行ったのは金閣寺、嵐山竹林、千本鳥居、清水寺、などなど
www.kyo-yado.com

かなり安く行けたと思う。

MySQLからデータをCSVで出力してExcelで開けるようにする

SELECT * FROM m_hogehoge
INTO OUTFILE '/tmp/m_hogehoge.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"';

nkf -s --overwrite /tmp/m_hogehoge.csv

いつもググっている気がする。CSVのエスケープ処理的なこともやってくれる。