mysql:7874
From: Shinya Kawaji <Shinya Kawaji <kawaji@xxxxxxxxxx>>
Date: Wed, 04 Jun 2003 11:08:57 +0900
Subject: [mysql 07874] Re: 日付検索について
かわじ、です。 余計なことをいくつか書いていますが、結論は後半の方にあります。 > 今回、新たにSQL文についてお聞きしたい事があります。 > > CREATE TABLE date_tb ( > date_id bigint(20) unsigned NOT NULL auto_increment, > date_name date NOT NULL default '0000-00-00', > PRIMARY KEY (date_id), > KEY date_id (date_id) > ) TYPE=MyISAM'; TYPE=MyISAM'; の後の ' が不要なのと、date_id に PRIMARY KEY と KEY の 両方を設定しているのは、あまり必要のないことでは? show index from date_tb; # それとも、何か効果があるのでしたら、後学のために教えて下されば幸いです > CREATE TABLE count_tb ( > count_id bigint(20) unsigned NOT NULL auto_increment, > count_name_id bigint(20) unsigned NOT NULL default '0', > count_date_id bigint(20) unsigned NOT NULL default '0', > count_i bigint(20) unsigned NOT NULL default '0', > count_j bigint(20) unsigned NOT NULL default '0', > count_e bigint(20) unsigned NOT NULL default '0', > PRIMARY KEY (count_id), > KEY count_id (count_id) > ) TYPE=MyISAM'; こちらも上記と同様。 > INSERT INTO count_tb VALUES (1,1,1,'','',1); > INSERT INTO count_tb VALUES (1,1,2,1,1,1); > INSERT INTO count_tb VALUES (1,1,3,'','',4); > INSERT INTO count_tb VALUES (1,2,3,2,3,''); > INSERT INTO count_tb VALUES (1,1,5,1,4,3); > INSERT INTO count_tb VALUES (1,1,6,2,1,''); > INSERT INTO count_tb VALUES (1,2,6,6,'',7); > INSERT INTO count_tb VALUES (1,1,7,1,4,3); VALUES の最初の項目(count_id)は、PRIMARY KEY だから、 複数の行に 1 を設定してもエラーになるはず。正確には以下のようでは? (私は 3.23.x ですが、4.x だと違うのかな?) INSERT INTO count_tb VALUES (NULL,1,1,'','',1); INSERT INTO count_tb VALUES (NULL,1,2,1,1,1); INSERT INTO count_tb VALUES (NULL,1,3,'','',4); INSERT INTO count_tb VALUES (NULL,2,3,2,3,''); INSERT INTO count_tb VALUES (NULL,1,5,1,4,3); INSERT INTO count_tb VALUES (NULL,1,6,2,1,''); INSERT INTO count_tb VALUES (NULL,2,6,6,'',7); INSERT INTO count_tb VALUES (NULL,1,7,1,4,3); > SELECT date_tb.date_name, count_tb.count_i, count_tb.count_e, count_tb.count_j > FROM date_tb LEFT JOIN count_tb ON date_tb.date_id = count_tb.count_date_id > WHERE count_tb.count_name_id = $name_id > and date_tb.date_name BETWEEN '2003-05-01' AND '2003-05-31' > ORDER BY date_tb.date_id"; これも最後の " が不要(プログラムのソースから抜いたからでしょうが)。 あと、表にはあった total が抜けています。 > と、したのですが、count_tb.count_name_id = $name_idがいけないのか、 > アクセスがない日のデータが取得出来ません。 > LEFT JOINって検索にヒットしなくても左側、すなわちdate_tbの情報は > 必ず出力するのではないのですか? > 私の考えでは、このSQL文で、5/1〜5/31までの、date_name は出力されて、 > count_tb.count_name_id = $name_idが、なかった場合、count_i等は > nullだと思ったのですが・・・。 (内部的な実装はともかく、理屈では)LEFT JOIN でテーブルが結合されてから、 そのテーブルに対し WHERE 節が評価されるはずですから、 WHERE count_tb.count_name_id = $name_id によって、 > count_tb.count_name_id = $name_idが、なかった場合 の行は結合されている結果のテーブルから全て排除されます。 よって、LEFT JOIN 時に 必要な条件を指定してやれば良いと思います。 SELECT date_tb.date_name, count_tb.count_i, count_tb.count_e, count_tb.count_j, count_tb.count_i + count_tb.count_e + count_tb.count_j as total FROM date_tb LEFT JOIN count_tb ON date_tb.date_id = count_tb.count_date_id and count_tb.count_name_id = $name_id WHERE date_tb.date_name BETWEEN '2003-05-01' AND '2003-05-31' ORDER BY date_tb.date_id ; しかし本来、以下の二つのフィールドの組み合わせは、 ユニークと仮定できるのでしょうか? count_tb.count_name_id count_tb.count_date_id もしユニークでなければ、上記のSQLでは駄目で(同じ日付の行が複数出力され る)、以下のようにする必要があります。この場合は、NULL ではなくて、0 が 出力されます。 SELECT date_tb.date_name, sum(count_tb.count_i) as count_i, sum(count_tb.count_e) as count_e, sum(count_tb.count_j) as count_j, sum(count_tb.count_i) + sum(count_tb.count_e) + sum(count_tb.count_j) as total FROM date_tb LEFT JOIN count_tb ON date_tb.date_id = count_tb.count_date_id and count_tb.count_name_id = $name_id WHERE date_tb.date_name BETWEEN '2003-05-01' AND '2003-05-31' GROUP BY date_tb.date_name ORDER BY date_tb.date_id ; また最初の > count_name_id(人名コード)が「1」のみの、5月分のカウントを集計しようとした場合、 > > |2003-05-01|2003-05-02|2003-05-03| > ―――+――――――+―――――+――――――+― > count_i| 0 | 1 | 0 | > count_j| 0 | 1 | 0 | > count_e| 1 | 1 | 4 | > total| 1 | 3 | 4 | > > と、出す方法が分からずご教授をお願いしたいと思いメールしました。 は、かなり難しいと思います。 一般的に SQL では、「項目を横に」「データを縦に」並べるので、それの 縦横逆は、SQL ではなく、プログラム側で処理する方が簡単だと思います。
7872 2003-06-04 08:34 ["Tatsuya Kondo" <kon] 日付検索について -> 7874 2003-06-04 11:08 ┗[Shinya Kawaji <kawaj] 7875 2003-06-04 18:57 ┗[<lavlav@xxxxxxxxxx> ]