[前][次][番号順一覧][スレッド一覧]

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> ]