Gmailでメールの振り分けを設定する方法
Outlookに慣れた人がGmailを仕事で使おうとすると戸惑う場合が多いと思う。なんせフォルダという概念がない。代わりにラベルというものがあるようなんだけれど「ラベル?おれはそういうのじゃなくてフォルダ分けしたいだけなんだけど」と思ったりする。ラベルとフォルダの違いは、ひとつのメールに対してラベルなら複数設定ができるがひとつのメールは複数のフォルダに所属できないということだ。
自分の場合はOutlookでは基本的なこんな感じで振り分けを行う。
- XXXプロジェクトのメーリングリストあては「XXXプロジェクト」というフォルダに
- 日本チーム全体のメールは「日本チーム」というフォルダに
- システムから自動配信されるエラー通知メールなんかはエラー通知に
- YYYサービスのメルマガとかほぼゴミみたいなメールは「ゴミ箱一歩手前」に
すると受信トレイに残ったものは従来のルールに当てはまらないものなので必ず目を通すべきものとなるので、受信トレイは常に空であるのが正常という状態を作る。(「to me」みたいな自分宛てのフォルダを作ることはしない)
この、「どのフォルダにも属さないメールのみを一覧表示する」というのがGmailでできなくて悩ましかった点なのだが、ようやくやり方を発見したので記録しておく。
1.ラベルの自動付加を設定する
まずは各メールにラベルが適切に付加されるよう設定をする。ラベルをつけたいメールを開いて右上のメニューから「メールの自動振り分け設定」を選択する。
その上で、ポップアップ下部の「この検索条件でフィルタを設定」をクリックし、
上から5番目にある「ラベルを付ける」にチェックを入れて最下部の「フィルタを作成」をクリックする。
2.マルチ受信トレイを有効化する
右上ギアメニューより「設定」>「Labs」を選択すると中段あたりに「マルチ受信トレイ」というものがあるので、これを有効化して「変更を保存」ボタンをクリックする。
次に右上ギアメニューより「設定」>「マルチ受信トレイ」を選び、パネル0の検索キーワードに"has:nouserlabels"と入れる。(パネル1の値は消してしまってOK)
3.振り分けルールを管理する
振り分けルールを追加しすぎてよくわからなくなってきた場合は右上ギアメニューより「設定」>「フィルタとブロック中のアドレス」を見ることで一覧で確認できる。
これで、一番上にはなんのラベルもついていないメールのみが表示される。(≒Outlookで言うところの受信フォルダ)
ちなみにこの"has:nouserlabels"というのはGmailがサポートしている種々の検索クエリのうちの一つで、それ以外にも以下のリンクのように数多くのクエリが存在するのでこれを使いこなすとかなり便利そうではある。
support.google.com
あと、フィルタとか振り分けとかUI上で用語が異なるのがちょっと気になる。
バスケット分析(併売分析)のためのSQL
いわゆる売上トランザクションテーブル、こんなデータから
OrderID | Date | ProductID | ・・・ |
---|---|---|---|
0000001 | 2017-07-01 | A001 | ・・・ |
0000001 | 2017-07-01 | A002 | ・・・ |
0000002 | 2017-07-02 | A003 | ・・・ |
0000003 | 2017-07-02 | A001 | ・・・ |
0000003 | 2017-07-02 | A002 | ・・・ |
0000003 | 2017-07-02 | A004 | ・・・ |
ある商品を買った人がほかの商品をどれだけ併売しているかを調べるためのこんなテーブルを作る。
YearMonth | MainProduct | SubProduct | # of Purchase |
---|---|---|---|
2017-07 | A001 | A002 | 2 |
2017-07 | A001 | A004 | 1 |
2017-07 | A002 | A001 | 2 |
2017-07 | A004 | A001 | 1 |
こんな感じでSQLを書く。書いてしまうと普通のクエリなんだけど、これがひらめいたときは結構感動した。
SELECT date_format(a.Date, '%Y-%m') YearMonth ,a.ProductID MainProduct ,b.ProductID SubProduct ,count(*) `# of Purchase` FROM Sales_T a ,Sales_T b WHERE a.OrderID = b.OrderID and a.ProductID <> b.ProductID GROUP BY date_format(a.Date, '%Y-%m') ,a.ProductID ,b.ProductID
月次累計を求めるSQL
こんなデータがあるときに
Date | Sales |
---|---|
2017-07-01 | 110 |
2017-07-02 | 120 |
2017-07-03 | 130 |
・・・ | ・・・ |
2017-07-31 | 410 |
2017-08-01 | 100 |
2017-08-02 | 110 |
ひとつカラムを追加して、月次累計(Monthly Running Total)を求めたい場合に
Date | Sales | MRT_Sales |
---|---|---|
2017-07-01 | 110 | 110 |
2017-07-02 | 120 | 230 |
2017-07-02 | 130 | 360 |
・・・ | ・・・ | ・・・ |
2017-07-31 | 410 | 8060 |
2017-08-01 | 100 | 100 |
2017-08-02 | 110 | 210 |
こんな感じでSQLを書く。ここで、GROUP BY 1,2はGROUP BY t1.Date,t1.Salesと同じ意味。
SELECT t1.Date ,t1.Sales ,sum(t2.Sales) RunningTotal_Sales FROM Daily_Sales t1 ,Daily_Sales t2 WHERE year(t1.Date)=year(t2.Date) AND month(t1.Date)=month(t2.Date) AND t1.Date >= t2.Date GROUP BY 1,2
ここでなぜsum(t2.Sales)が月次累計になるかというと、以下のように集計を外したSQLを書くと
SELECT t1.Date ,t1.Sales ,t2.Sales t2_Sales FROM Daily_Sales t1 ,Daily_Sales t2 WHERE year(t1.Date)=year(t2.Date) AND month(t1.Date)=month(t2.Date) AND t1.Date >= t2.Date
こんな感じの結果セットが取得できる。(1日目は1レコード、2日目は2レコード、・・・31日目は31レコード)
Date | Sales | t2_Sales | |
---|---|---|---|
2017-07-01 | 110 | 110 | |
2017-07-02 | 120 | 110 | ←7/1の値 |
2017-07-02 | 120 | 120 | |
2017-07-03 | 130 | 110 | ←7/1の値 |
2017-07-03 | 130 | 120 | ←7/2の値 |
2017-07-03 | 130 | 130 | |
・・・ | ・・・ | ・・・ | |
2017-08-01 | 100 | 100 | |
2017-08-02 | 110 | 100 | ←8/1の値 |
2017-08-02 | 110 | 110 |
これに対してsum(t2.Sales) GROUP BY t1.Date,t1.Salesをするので、月次累計となる。
もし日ごと製品カテゴリごとの売上というテーブルがあった場合は、同様にSELECT句・WHERE句・GROUP BY句に製品カテゴリを含めればOK。
MySQLでカレンダーテーブルを作る
自分がよく使うSQLをライブラリ的にここに残しておく。
こんな感じでSQLを書くと
SELECT @date:=date(date_format(CURRENT_DATE(),'%Y-%m-01')) as Date UNION ALL SELECT @date:=DATE_ADD(@date, INTERVAL 1 DAY) FROM `テーブル名` WHERE @date < last_day(CURRENT_DATE())
こんな感じで結果セットが取れる。
Date |
---|
2017-08-01 |
2017-08-02 |
・・・ |
2017-08-31 |
この時、SQLの中で参照するテーブルはどんな構造になっていてもかまわないけれど、ここで取得する日付範囲よりも多いレコードを持っている必要がある。
例えば上の例でいえば`テーブル名`は30レコード以上持っている必要がある。
JavaScript再入門4 - call, apply, bind
JavaScript再入門3 - thisは何を意味するか - おれの技術日記の続き。
例によってこちらにお世話になります。
最強オブジェクト指向言語 JavaScript 再入門!
7. call/applyを使ってthisをコントロールしつつ関数をコールする。
前回のブログの中で、thisというのはコンテキストによって可変で関数実行時に決定されるということがわかった。
このthisをコントロールしつつ関数を呼び出すのがcallとapply。この二つは記述方式こそ違うものの、やっていることは本質的に同じ。
・関数内でのthisが何か
・呼び出すときの引数は何か
というのを指定しつつその関数を実行する。
callとapplyは以下のようなシンタックスで使用される。ここでobjectは関数内でのthisにあたり、arg1以降は関数を呼び出す時に渡される引数となる。call関数は可変長引数であるのに対して、apply関数はArrayを第二引数にとる。
call(object, arg1 ,arg2...) apply(object, [arg1,arg2,...])
例えば以下のようなコードの場合、func1は3回呼び出され全く同じ結果となる。
function func1(){ console.log("123"); } func1();//123が表示される func1.call();//123が表示される func1.apply();//123が表示される
以下のようなコードの場合、最初のコールではthisがwindowオブジェクトになってしまうがwindowオブジェクトにname属性は存在しないためthis.nameは空になる(undefinedにならないのはなんでだろう・・・)。一方でcall・applyを通じてコールする時に引数にobjを渡しているので、this=objとなりname属性の値がログ出力される。
function func1(){ console.log("log:" + this.name); } var obj = { name:"obj_name", } func1();//log:だけがコンソール出力される func1.call(obj);//log:obj_nameがコンソール出力される func1.apply(obj);//log:obj_nameがコンソール出力される
これはfunc1に引数が存在する場合の呼び出し方。callでもapplyでも、可変長引数なのか配列を渡すのかの違いだけで結果は一緒。
function func1(param1, param2){ console.log("log:" + this.name + ":" + param1 + param2); } var obj = { name:"obj_name", } func1.call(obj, "this is ", "test");//log:obj_name:this is testがコンソール出力される func1.apply(obj, ["this is ", "test"]);//log:obj_name:this is testがコンソール出力される
8. bindを使って関数内のthisを固定化する。
通常は関数とオブジェクトには何の関連もなく、関数が呼び出されたときにその状況によってthisの値が決定される。しかしbind関数を使えば実際の関数呼び出しの前にthisを固定化することができる。
以下のコードではfunc2はobjとbindされているためthisの値が存在するが、func1はbindされていないのでthis.nameが空となる。
function func1(param1, param2){ console.log("log:" + this.name + ":" + param1 + param2); } var obj = { name:"obj_name", } var func2 = func1.bind(obj); func2("this is ", "test");//log:obj_name:this is testがコンソール出力される func1("this is ", "test");//log::this is testがコンソール出力される
という仕様は理解したものの、実際どういうところで使うんだろう・・・・大規模なJavaScriptでの開発とかやってみたい。
依然として今後の課題
Apply関数って何?→thisをコントロールするためのものらしい- (function() {})();とかいう記法→即時関数というらしい
thisのスコープの考え方
JavaScript再入門3 - thisは何を意味するか
例によってこちらにお世話になります。
最強オブジェクト指向言語 JavaScript 再入門!
6. thisの解釈は状況によっていろいろ。
Javaにおいてthisといえば非常に明確で、インスタンス変数を明示的に指定するとかインスタンスのメソッドを呼ぶときにsuperでなくthisなのよってな感じで書くものであった。しかしJavaScriptにおいてthisというのはコンテキストによって全く異なる意味合いを持つ。
ルール1:グローバルスコープにおいて、thisはwindowを指す
これは非常に簡単。windowがオブジェクトの起点なのでグローバルスコープにおいてthisはwindowとなるというのは納得できる。
//グローバルスコープ console.log(this);//1番目のthis、windowを指す
ルール2:関数呼び出しにおいて、thisはwindowを指す
まあこれもそういうもんかという感じ。
function global_function(){ console.log(this); } global_function();//2番目のthis、windowを指す
ルール3:メソッド呼び出しにおいて、thisはメソッドが呼ばれたインスタンスを指す
じゃあ次にこれは?というとここでのthisはObject {method1: function}となる。ここら辺までは想定の範囲内。
var obj = { method1:function (){ console.log(this); } } obj.method1();//3番目のthis、上のobjを指す
ルール4:入れ子になった関数において、thisはwindowを指す
これはだいぶ意味不明なんだが、そういうもんとして覚えるしかなさそう。thisにおいてスコープチェーン的な考え方は通用しない。
var obj = { method1:function (){ var method2=function(){ console.log(this); } method2(); } } obj.method1();//4番目のthis、windowを指す
ルール5:これらルールに基づき、thisが何を指し示すかは処理の"実行時"に決定する
以下のコードでglobal_functionは2回呼ばれているが、全く同じ処理であるにも関わらずそれぞれの指し示すthisはその関数が呼ばれる状況によって異なっている。(=thisは実行時に決定される)
function global_function(){ console.log(this); } global_function();//2番目のthis、windowを指す var obj = {} obj.method2 = global_function; obj.method2();//4番目のthis、上のobjを指す
だいぶお腹いっぱいになってきたので今日はこのへんで。
依然として今後の課題
- Apply関数って何?→thisをコントロールするためのものらしい
- (function() {})();とかいう記法→即時関数というらしい
thisのスコープの考え方
JavaScript再入門2 - スコープチェーンとクロージャ
JavaScript再入門1- プロトタイプチェーンとコンストラクタ関数 - おれの技術日記の続き。
例によってこちらにお世話になります。
最強オブジェクト指向言語 JavaScript 再入門!
4. 変数のスコープはグローバル/ローカルのみ、スコープチェーンのルールに従い内側のスコープから順次走査・参照される
CとかJavaとかだとローカル変数のスコープはブロックを単位としているので、例えば以下のようなコードはコンパイルエラーになってそもそも実行できないが、JavaScriptでは合法。ここで宣言された変数a, bはその関数内のどこでも参照することができる。
function func1(){ var a = 1; if(何らかの条件){ var b = 3; } alert(b); }
JavaScriptはみょうちくりんな言語なので関数を入れ子にすることもできるんだが、では次にこうするとどうなるか。
function func1(){ var a = 1; function func2(){ var b = 2; } alert(b);//ここでReferenceError } func1();
内側の関数の中で宣言された変数に対して外側の関数からはアクセスすることができず、ReferenceErrorとなる。ブロックレベルのスコープは存在しないが関数の入れ子による変数スコープの制限は有効。
グローバル変数 | ローカル変数 |
---|---|
関数の外で宣言した変数 | 関数の内側で宣言した変数・関数の仮引数 |
プロセス全体で参照できる | その関数の内側からのみ参照できる |
次にこんなコードを書いてみると、これは動く。
var c = 3 function func1(){ var a = 1; function func2(){ var b = 2; //一番内側の関数からはその外側の変数を参照できる alert(a+b+c);//"6"となる } func2(); } func1();
func2で参照された変数は一番内側のスコープをまず走査し、見つからなければもうひとつ外のfunc1のスコープを走査し、最後にグローバルスコープを走査する(もしそれでも見つかれなければエラーになる)。このようにして内側から外側に順次走査する機構をスコープチェーンという。ちなみに、複数のスコープで同一名の変数を宣言した場合には、このルールに従って一番最初に見つかったほう(=より内側の変数)が参照される。
5. クロージャを使ってグローバルスコープを汚さずに状態を管理する
先ほど行ったようにJavaScriptでは関数の中にさらに関数を定義することができるが、内側の関数をスコープ外から呼び出すことができるか。と思ってこんなコードを書いてみたら、やはり最後の行のfunc2()は参照できずエラーになった。
function func1(){ var a = 1; function func2(){ var b = 2; alert(a+b); } func2(); } func1();//これはOK func2();//これはエラーになる
このスコープの妙を利用して、以下のように関数内に変数の状態を保持させ続けることができる。このようなやり方をクロージャという。
function func1(){ var a = 1; return function(){ alert(a); a+=1; } } var f = func1(); var f2 = func1(); f();//1がアラートされる f();//2がアラートされる f();//3がアラートされる f2();//1がアラートされる
ちなみに、「この程度ならグローバル変数でもできるのでは?」と思われる方もいると思うが(というか私も思った)、クロージャはグローバルスコープを汚さずに状態を維持するために使うらしい。クロージャの手順は以下の通り。
- 関数を入れ子に定義する
- 外側の関数に変数を宣言する
- 内側の関数からその変数を操作する
- 内側の関数を外側の関数の戻り値にする
依然として疑問なのは
- この例だと関数の参照をグローバルで持ち続けないといけないから結局グローバルスコープは汚れるのでは?
- JavaでいうとこのBeanオブジェクトみたいなん作るときにうれしいのかな?でもそれならコンストラクタ関数でもおんなじことできるしな・・・
- 結局使いどころがピンとこないぞ、ググってもカウンタの例ばっかり出てくる
まあ、これはおいおいわかってくるんでしょう・・
依然として今後の課題
- Apply関数って何?
- (function() {})();とかいう記法→即時関数というらしい
- thisのスコープの考え方