私がたばこをやめられた方法

約2年前にたばこやめましたというエントリの中で「1年後にたばこをやめた状態を継続できていたら、たばこをやめられる(やめられた)具体的な方法を記す」と書いておいて、今日に至るまですっかり忘れていたのを思い出した。

結論から言うと、たばこをやめた状態は継続できている。

というわけで、予告より1年遅れてしまったが、私がたばこをやめた(やめられた)方法を書き記そうと思う。

以前のエントリと重なってしまうが、私が採用した方法は、減煙法と断煙法を合わせた方法で、禁煙パイポとフリスクを使用したものである。

やめるにあたっては、下の図に表したような7つの段階を踏んで実践した。

説明の都合上、7つの段階となっているが、実践した当時に目標としていたのは、「たばこへの依存からの脱出」ただ一つである。

そして、「たばこへの依存」から脱するには、以下の3つから抜け出す必要があると思う。

  1. たばこの質への依存
  2. たばこの量への依存
  3. たばこの存在への依存

1.たばこの質への依存

ここで言う質とは、ニコチン・タール量が多い少ないという、たばこの質への依存という意味。

いきなりニコチン・タール量の多いたばこをやめて「物足りない」と感じることがないように、ニコチン・タール量の少ないたばこに段階的に切り替える。

「ニコチン・タール量の少ないたばこに切り替えたら、吸った気がしない。だからたばこの本数が増える」というのは、思い込みに過ぎない

たとえ事実だとしても、物事の捉え方考え方ひとつで、たばこの本数は増やさずにニコチン・タール量の少ないたばこに切り替えることは可能。

私の場合は、マイルドセブン→同ライト→同スーパーライトへと段階的にニコチン・タール量の少ないたばこへ切り替えた。全く抵抗がなかったわけではないが、購入してしまえば後の祭り。

2.たばこの量への依存

「たばこの質への依存」を減らすことに慣れてきたら、次は「たばこの量への依存」を減らす。

質の問題とは違い、量の問題は「喫煙する」という行動の回数が直接関係する。

この回数を減らすために、私は以下のような3つのルールを設けて実施した。

  • 喫煙する条件をできるだけ持たない
  • 喫煙する場所にできるだけ行かない
  • 喫煙できる場所では、自分が喫煙していい場所かどうかを自分で設定する

「喫煙する条件」とは、ライターや携帯灰皿などの喫煙具を指しており、それらをできるだけ持ち歩かないようにし、代わりに「禁煙パイポ」とフリスクを常に持ち歩くようにした。

次の「喫煙する場所」とは、喫煙ルームや喫煙エリアのような「喫煙するために設けられた場所」を指し、最後の「喫煙できる場所」とはファミレスの喫煙席や自宅などを指している。

私の場合は、自宅は「喫煙できる場所」だが、自分で「一人では喫煙してはいけない場所」と設定した。

上記の3つのルールを実施しながら徐々にたばこの量を減らし、フリスクの量を増やしていき、たばこを最終的にメンソールに切り替えた。

また、たばこの本数は、「1日○本まで」という制限は特に設けない代わりに、「今日は○本も吸ってしまった」という結果を意識していた。

ここまでは、図で言えば第1段階から第3段階に相当する。

3.たばこの存在への依存

ここからは、図で言うところの第4段階から第6段階に相当する。

この段階に突入したら、たばこを手にしないように心がける。

具体的には、たばこや喫煙具を意図的に忘れて持ち歩かないようにして、「毎日持ち歩く」という習慣を継続しないようにしたり。

「たばこを手にしない」ことをできるだけ継続することで、そのうち目にしても手にしないで済むようになる。

そうして頃合を見計らって、たばこを捨ててしまう。たばこを捨てるときは、残り数本であろうが、丸ごとであろうが全て捨ててしまう。

とにかくやめるときに一番大切なのは、必ずいきなり0本にすること=断煙することである。

また禁煙パイポも、たばこに併せて捨ててしまう。これは、たばこを連想させる「口にくわえる」という行為そのものをなくすため。

最後の第7段階の「フリスクを減らす」作業は、特に意識しなくてもさすがに食べ飽きるので、自然に減る。

以上の段階を踏むことで、私はたばこを完全にやめることができた。

※図を見ると、フリスクの摂取量が多いように見えるかもしれないけれど、そんなに摂取しているわけではない。念のためw。

2009年12月27日(日) 23時08分  

歯抜けのIDを全て求める

ここ最近のアクセスログを閲覧してみたところ、歯抜けのIDの求め方を探している方が多いことに気づいたので、自分でもちょっと考えてみた。

過去のエントリで紹介した方法は歯抜けの最小値を求めるもので、今回は指定した範囲の歯抜けを全て求めるものである。

今回の方法でもmin関数を使って歯抜けの最小値は求めることができる。

動作検証はMySQLで行なっているけれど特別な関数は全く使用していないので、他のデータベースでもほんの少し修正(Oracleの場合はfrom dualを追加するとか)するだけで動作すると思う。

作成したtablenameテーブルのIDカラムは数値型で、現在(2, 3, 5, 7, 11)が使用済みであり、歯抜け状態になっている。

mysql>  select id from tablename;
+----+
| id |
+----+
|  2 |
|  3 |
|  5 |
|  7 |
| 11 |
+----+
5 rows in set (0.05 sec)

このtablenameテーブルから使用されていないID(1, 4, 6, 8, 9, 10)を求めるSQL文は、以下のようになった。

mysql>  select id
    ->  from (
    ->  select (ones.num + tens.num + 1) id
    ->  from (
    ->  select 0 num union all
    ->  select 1 num union all
    ->  select 2 num union all
    ->  select 3 num union all
    ->  select 4 num union all
    ->  select 5 num union all
    ->  select 6 num union all
    ->  select 7 num union all
    ->  select 8 num union all
    ->  select 9 num) ones
    ->  cross join
    ->  (
    ->  select 0 num union all
    ->  select 10 num union all
    ->  select 20 num union all
    ->  select 30 num union all
    ->  select 40 num union all
    ->  select 50 num union all
    ->  select 60 num union all
    ->  select 70 num union all
    ->  select 80 num union all
    ->  select 90 num) tens
    ->  ) dummy
    ->  where dummy.id not in (select tablename.id from tablename)
    ->  and dummy.id < (select max(tablename.id) from tablename);
+----+
| id |
+----+
|  1 |
|  4 |
|  6 |
|  8 |
|  9 |
| 10 |
+----+
6 rows in set (0.05 sec)

自分が持っている知識で思いついたのは、上記の他にはexcept(差集合)演算を用いた方法(下記)。

けれどもMySQLではexcept(差集合)演算がまだサポートされていないので、以下のSQL文はOracleで動作検証。

Oracleでexcept(差集合)演算を行なうには、minus演算子を使う。

 select id
 from (
   select (ones.num + tens.num + 1) id
   from (
     select 0 num from dual union all
     select 1 num from dual union all
     select 2 num from dual union all
     select 3 num from dual union all
     select 4 num from dual union all
     select 5 num from dual union all
     select 6 num from dual union all
     select 7 num from dual union all
     select 8 num from dual union all
     select 9 num from dual
   ) ones
   cross join
   (
     select 0 num from dual union all
     select 10 num from dual union all
     select 20 num from dual union all
     select 30 num from dual union all
     select 40 num from dual union all
     select 50 num from dual union all
     select 60 num from dual union all
     select 70 num from dual union all
     select 80 num from dual union all
     select 90 num from dual
   ) tens
 ) dummy
 where dummy.id < (select max(tablename.id) from tablename)
 minus
 select id from tablename;

最初のSQL文との違いは、where節の条件のうち

    -> dummy.id not in (select tablename.id from tablename)

の条件文が削除されて、

 minus
 select id from tablename;

が追加される。

どちらにしても、もっとスマートで冴えた方法があると思う。きっと。

なので、ここで紹介した歯抜けのIDを求める方法は、数多くある方法のひとつ(いや、ふたつか)として参考にしていただければ幸いである。

ちなみに上記の最初に紹介したSQL文は、初めてのSQLの10章「結合」で紹介されているSQL文の応用である(書籍を奥から引っ張り出して確認しました)。

同書の内容はMySQLを基準に書かれているが、MySQL特有の機能に依存している部分は少なく、ところどころでOracleやSQL Serverとの差異や互換性を例に挙げてSQLの基本構文を紹介している(同書によれば、本文中のサンプルはOracleやSQL Serverでも動作するらしい)。

これからSQLを勉強する方や、データベーススペシャリストを勉強する方にも、興味があれば一読をお勧めする。

4873112818.09.MZZZZZZZ.jpgAmazon.co.jp: 初めてのSQL

2009年12月26日(土) 23時11分  

応用情報技術者試験結果

午前71.25点、 午後58.00点で不合格。あと1~2問正解していたら合格だったのに(苦笑)
悔しい~!!

ま、不合格は不合格ですな。

2009年12月23日(水) 23時55分  

Oracleと空文字とNULL

そうか、Oracleは空文字をNULLとして扱うのか……。

なんだか違和感を感じる。

慣れ親しんでいるのは上の図のようなイメージだけど、Oracleの場合は下の図のようなイメージ?

「” IS NULL」がTRUEになるのはちょっと不思議。

使いづらいような気がするけれど、慣れの問題なのかな(苦笑)

2009年12月20日(日) 23時03分  

MySQLでOracleのrownumのような行番号を付加する

MySQLでOracleのrownumのような行番号を付加する方法として、Web上でよく見かけるのは以下のようなユーザー変数を使ったSQL文で、2つのSQL文を発行しなければならない。

set @i:=0;
select @i:=@i+1 as rownum,user_id from user;

しかし、kotori::logで紹介されていた方法を用いれば、1回のSQL文で付加することができる。メモメモ。

select @i:=@i+1 as rownum,user_id from (select @i:=0) as dummy,user;

なるほど。サブクエリでユーザー変数を初期化しているのね。

で、ふとorder by節で並び替えた時の挙動が気になったので、早速試してみた。

全部で4つ試していて、始めの2つがテーブルのidカラムで並び替え(昇順、降順)、残りの2つ(3つ目と4つ目)が生成したrownumで並び替えたものである。

1つ目。

mysql>  select @i := @i + 1 rownum, id
    ->  from (select @i := 0) dummy, tablename
    ->  order by id asc;
+--------+----+
| rownum | id |
+--------+----+
|      1 |  2 |
|      2 |  3 |
|      3 |  5 |
|      4 |  7 |
|      5 | 11 |
+--------+----+
5 rows in set (0.00 sec)

2つ目。

mysql>  select @i := @i + 1 rownum, id
    ->  from (select @i:= 0) dummy, tablename
    ->  order by id desc;
+--------+----+
| rownum | id |
+--------+----+
|      1 | 11 |
|      2 |  7 |
|      3 |  5 |
|      4 |  3 |
|      5 |  2 |
+--------+----+
5 rows in set (0.00 sec)

3つ目

mysql>  select @i := @i + 1 rownum, id
    ->  from (select @i := 0) dummy, tablename
    ->  order by rownum asc;
+--------+----+
| rownum | id |
+--------+----+
|      1 |  2 |
|      2 |  3 |
|      3 |  5 |
|      4 |  7 |
|      5 | 11 |
+--------+----+
5 rows in set (0.00 sec)

4つ目

mysql>  select @i := @i + 1 rownum, id
    ->  from (select @i := 0) dummy, tablename
    ->  order by rownum desc;
+--------+----+
| rownum | id |
+--------+----+
|      5 | 11 |
|      4 |  7 |
|      3 |  5 |
|      2 |  3 |
|      1 |  2 |
+--------+----+
5 rows in set (0.00 sec)

う~ん。2つ目のSQL文の結果が予想していた結果と異なっている。予想していた結果は4つ目のSQL文と同様の結果だったのだけれど……。

Oracleで以下のようなSQL文を書いて確認してみたが、どちらも4つ目と同じ結果。

 select rownum, id from tablename order by id desc;
 select rownum, id from tablename order by rownum desc;

となると2つ目のSQL文は、4つ目のSQLと比べて

@i := @i + 1 rownum

を評価するタイミングが違うということになる。

2つ目のSQL文では、idカラムで並び替えた後に評価されているように見える。

というわけで調べてみたところ、MySQLのサイトの8.4. ユーザによって定義された変数のページで以下のような説明が。

ユーザ変数の評価順序は定義されておらず、与えられたクエリ内の要素に基づいて変更されることがあります。SELECT @a, @a := @a+1 ...では、MySQLは@aを先に評価し次に割り当てが実行されるように見えますが、クエリの変更(例えばGROUP BYHAVINGまたはORDER BY節による変更)は評価順序を変更する可能性があります。

このエントリで紹介したrownumもどきは、使用する時に注意が必要ですな。

2009年12月19日(土) 23時11分  

Webブラウザからコマンドライン版Webキャプチャーを実行(その2)

昨日の続き。無事、PHPからコマンドライン版Webキャプチャーを起動することができるようになったので、次はクライアント寄りのプログラムの作成。

言語はPHPとJavaScriptを使用。JavaScriptはJQueryも少し使用。

クロスブラウザ対応が面倒なので……。

そうしてできたのが、下のようなもの。

ところどころ手を抜いているけれど、一応動いてます。実際に動いているやつはこちら

対象サイトによってはキャプチャーに失敗することがあるみたい……。

※自宅Webサーバーを停止しているときは動きませんので、あしからず。

2009年12月06日(日) 23時44分  

Webブラウザからコマンドライン版Webキャプチャーを実行(その1)

先月作成したWebページキャプチャーのコマンドライン版を、Webブラウザから実行できるようにしてみようと思い立つ。
やろうとしていることは下のようなもの。適当に書いたので、間違っているかもいないかも。

クライアントPCから直接自宅Webサーバーにアクセスしていないのは、自宅Webサーバーをできるだけ外部に晒したくないのと、動的にIPが変わるという理由から。無料DDNSサービスを利用すれば済む話なのだけれど。

VBS+Perlを使って15分毎に自宅WebサーバーのIPアドレスを取得&更新しているけれど、今のところ特に困っていない。

さて、本題。手始めに自宅Webサーバーにコマンドライン版Webキャプチャーを起動するPHPを書いたのだけれど、きちんと実行してくれない。
コマンドプロンプトから実行すると問題なく実行してくれるのだが、PHPから起動すると、起動してそのままプロセスが終了せずにタイムアウトとなってしまう。
調べてみた結果、どうやらシステムアカウント権限で実行されていることが原因であることがわかった。コマンドライン版WebキャプチャーをAdobe AIRで作成しているため、同時にAdobe AIR Updater(下図)も実行されて、これが待ち状態になっているらしい。システムアカウント権限で実行されているので、プロセス上に存在していても表示されていないので、手が出せず(苦笑)

ならばユーザーアカウント権限で起動してやればと思い、runasコマンドで起動を試みるもユーザーアカウント権限で起動する際のユーザーアカウントのパスワード入力の段階でアウト。どうもシステムアカウント権限からユーザーアカウント権限で起動することはできないっぽい(苦笑)

結局、PHPを起動しているApacheをユーザーアカウント権限で再起動することで解決。

無事、PHPからコマンドライン版Webキャプチャーを実行することに成功。やれやれ。

2009年12月05日(土) 23時33分