重複行

2009/01/09 | MySQL

開発を始めて間もない頃に作ったサイトをリニューアル中。まだまだ駆け出しの頃だったので、プログラムもデータベースの構造もひどいものだ(だからサイトが重い)。そんなサイトでも月間数万ページビューあるのでリニューアルすることにしたのだ。

プログラムは全て新しく書き直すので、以前のプログラムはまったく気にならないけど、データベースの構造が大変。古いのをそのまま持ってくるのも重そうだし。新しく設計しなおしてデータをコンバートする過程で問題が起きた。テーブルに主キーを設定していなかったので、データの重複が起こっていた。そもそもプログラム側でも特に制御していなかったし、重複が起こっても当時のプログラムでは問題にならなかったのだが、今回はしっかりと主キーを設定したが故に、一筋縄では移行できなくなってしまったわけだ。

データの重複を削除する方法をウェブで探したら、ちゃんと見つかった。

CREATE TABLE temp as SELECT * FROM original GROUP BY column1, column2
DROP TABLE original
ALTER TABLE temp RENAME TO original

最初に、元のテーブルから全ての列をグループ化して、別名でテーブルを作る(この時点で重複行は一つにまとめられている)。次に元のテーブルを消して、最後にテーブル名を変更してそれで完了。ちょっとキツネにつままれたような感じだけどすごく簡単にできた。ほんとに大丈夫なのかどうかわからないんだけど、とりあえずこれでよしとした。

datetime型をunix timestampに一発変換

2009/01/08 | MySQL

最近はあまり使うことはないのだが、以前はカラムを定義する際にdatetime型やdate型をよく使っていた(最近はint型にしてunix timestampでデータを入れるのが好き)。当然のことながら昔作ったプログラムをリニューアルするとき、違和感を覚えることがある。そんなときに便利な関数がunix_timestamp。例えばSELECT文で、以下のように使用する。

SELECT unix_timestamp(timestamp_type_column) FROM table

これでdatetime型やdate型の値をunix timestampにして返してくれる(ちなみにその逆の関数はfrom_unixtime)。SQL文を発行する際にその都度関数を呼び出してもいいだろうけど、それではオーバーヘッドがバカにならないこともある(もちろん相応の負荷があるサイトの場合だが)。なので、元のテーブルを、上記の関数やその他の関数を使って一旦吐き出し、新しいテーブルを作ってそこにデータを流し込むほうがいい。でも、型の変更が原因で諸々問題が出る可能性があることを理解して使わないといけないけれど。

ランダムで取得してページング

2008/07/20 | MySQL

データをランダムな順番で取得するには以下のorder句をつければいいということは前に書いた。

order by rand()

これで確かにランダムな順番でデータを吐き出してくれるのだが、SQL実行毎に順番が変わってしまう(当たり前)。ページング処理を実行したい場合は、1ページ目と2ページ目を表示する際に、順番に(例えば)10件ずつデータを取ってくるわけだが、そもそも順番がめちゃくちゃなので、1ページ目のデータが2ページ目でまた出現してしまう、といったことが起きてしまう。どうすればよいか。解決策がコレ。

order by rand(n)
nは適当な数値

詳しくは調べていないがnは乱数を発生させる際のseed値のようなもの。このseed値が同じであれば、並び順は常に同じになるのだ。なのでデータ取得の一番最初のときにこのseed値を初期化して、以降のページングの際はこのseed値を持ちまわってSQL文に仕込んでやればよいということになる。

ランダム順で取得

2008/06/19 | MySQL

データをランダムに取得するには、たいていどのような仕組みにでも乱数ジェネレータ(もしくはそれらしきもの)が用意されていて、それを利用するのが便利。MySQLからランダムに値を取得する場合、以下のようにORDER BY句にRAND()関数をかませると、ランダムな順番で取得できる。

SELECT * FROM table ORDER BY RAND();

ランダムに3つ取得したいならLIMIT 0,3とかつけてあげればよい。

想定外の文字にマッチしてしまう

2006/12/03 | MySQL

mysqlで用語集を作ってみたのだが、ちょっとした問題がでた。
この仕組みでは読み仮名を登録するようにしてあるのだが、五十音で整理したいため、読み仮名の最初の文字を取り出して別カラムで格納している(例えば「ガチョウ」という単語があった場合は、そのままでは「ガ」になってしまうが、ちょっと処理をして「カ」を取り出している)。
ここで問題。「ツ」という文字を検索するときに「ツ」で検索して表示されるのはもちろんだが「テ」で検索しても表示されてしまう。また「ル」という文字を検索するときに「ト」で検索しても表示されてしまう。なぜ?、なぜ?。
理由を突き詰めなかったが、なんとなく想像がついたのでカラムをbinaryとして保存するよう変更した。これで解決。
きっと少し考えれば理由もわかるとは思うがあえて調べない(面倒だし、理由を知らなくても直感でわかることだから)。でももし親切に教えてくれる人がいらっしゃるようでしたら、コメントに残してください。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net