mysqlのレコード数取得に関する質問です。


会員の情報はUserというテーブルに入っています。
総会員数は

$rs = mysql_query("select count(*) from User", $con);
$count = mysql_fetch_row($rs);

echo $count[0] . '件';

上記で表示できるのですが

今日増えた会員数
昨日増えた会員数

を新たに表示するにはどうすればよいでしょうか?
入会日はフィールドJoinedに記録されています。

またキャリア別総会員数も表示したいです。
ユーザのキャリアはフィールドCarrierに記録されています。

1=pc
2=docomo
3=softbank
4=au

以上3つの条件抽出したレコード数を表示したいです。
ご教授いただけると幸いです。
よろしくお願い致します。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2009/03/15 09:12:50
  • 終了:2009/03/15 15:07:31

回答(3件)

id:moom0906 No.1

moom0906回答回数9ベストアンサー獲得回数12009/03/15 09:47:35

次のようなSQLでどうでしょう

  • 日時関数を参考

http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/mysql_16.htm

○ キャリア別

SELECT Carrier, count(*)

FROM User

GROUP BY Carrier


○ 特定の日のみ

SELECT count(*) FROM `User`

WHERE date_format(Joined, '%y.%m.%d') = 'XXXX.XX.XX'

'XXXX.XX.XX'の部分を対象の日付に。

ちなみにMySQLは0保管される(3月⇒03)なので注意


○ 特定の日のみ かつ キャリア別

SELECT Carrier, count(*) FROM `User`

WHERE date_format(Joined, '%y.%m.%d') = 'XXXX.XX.XX'

GROUP BY Carrier


'XXXX.XX.XX'の部分を対象の日付に。

ちなみにMySQLは0保管される(3月⇒03)なので注意


---- 以下は参考程度 ----

○ユーザ数が多い場合上記のSQLは性能問題になるので、WHERE句の部分を変更する。

いままでの例はプログラム部分が少なめの例です。インデックスが効かず遅くなります。

(Joinedにインデックスが設定されていることが前提です)

SELECT Carrier, count(*) FROM `User`

WHERE Joined >= 'XXXX.XX.XX' AND Joined < 'XXXX.XX.XX'

GROUP BY Carrier

最初の'XXXX.XX.XX'に対象の日、後半の'XXXX.XX.XX'にはその翌日

二つ作る必要がある

id:xptree

回答ありがとうございます。

キャリア別は1件で

特定の日のみは0件になってしまいます

2009/03/15 12:33:18
id:shiroxcom No.2

しろっくす回答回数140ベストアンサー獲得回数52009/03/15 09:46:58

仮にJoinedの値がdatetimeだと仮定しますと、

今日増えた会員数

は、

select count(*) from User whrere Joined like '2009-01-01%'; 

昨日増えた会員数

は、

select count(*) from User whrere Joined like '2008-12-31%'; 

など、になります。

しかしながら、

Joinedの型を明示されてないので、答えるのが難しいです。

Joinedの型を明示されて、もう一度質問しなおすのがよろしいかと思います。

その場合はポイントは結構です。

がんばってください。

因みに下記の本は超おススメです。

僕もこれから勉強しました。

http://www.amazon.co.jp/MySQL%E5%85%A5%E9%96%80%E4%BB%A5%E5%89%8...

id:xptree

回答ありがとうございます。

型はdatetimeです。

表示されないのですが…

$rs = mysql_query("select count(*) from User whrere Joined like '2009-01-01%'");

でいいのでしょうか?

2009/03/15 12:31:19
id:shiroxcom No.3

しろっくす回答回数140ベストアンサー獲得回数52009/03/15 09:51:05

すみません。

最後のキャリアの部分を見落としてました。

select count(*) from Carrier='pc';

で大丈夫と思います。

http://google.co.jp/

  • id:pahoo
    フィールドJoinedの型は何ですか?
    Date/Datetime/Timestamp/charのいずれですか?
  • id:xptree
    コメントありがとうございます。
    Datetimeです
  • id:chuken_kenkou
    >$rs = mysql_query("select count(*) from User whrere Joined like '2009-01-01%'");

    whereの綴りが間違っています。

    ×whrere

    ○where


    >ユーザのキャリアはフィールドCarrierに記録されています。
    >
    >1=pc
    >2=docomo
    >3=softbank
    >4=au


    Carrier列のデータ型は何ですか?
    1、2などの数値を入れているのか、pcなどの文字を入れているのか、提示内容では判別できません。


    >今日増えた会員数
    >昨日増えた会員数

    MySQLから日付を得るなら、

    今日
    current_date

    昨日
    current_date - interval 1 day

    などで得られます。

    where date(Joined)=current_date



    where date(Joined)=current_date-interval 1 day

    といった形で利用できます。

    特定日の指定なら、

    where date(Joined)='2009-03-15'

    など、yyyy-mm-dd形式で、文字で指定できます。

  • id:xptree
    chuken_kenkou さん回答ありがとうございます
    昨日/今日の会員数は表示されるようになりました。
    この質問はキャンセルし、chuken_kenkou さんへポイントを送付致します。

    Carrierのフィールドタイプはsmallint(6)です。
    よろしくお願いします。
  • id:chuken_kenkou
    まず、前置きです。

    MySQLの質問をする場合、バージョンを明記するようにしてください。

    MySQL 4.0以前・・・一部のジョイン、union、一時表などは実装済
    MySQL 4.1・・・ジョインの拡張、サブクエリ、unicodeなどの実装
    MySQL 5.0・・・ビュー、ストアドプロシジャ、トリガなどの実装

    と、すぐ思いつくものでも「SQLでの実装」に使える機能が、大きく違ってきます。

    英単語などを表名、列名などにすると、RDBMSの予約語とぶつかったりして、思わぬ文法エラーになったりします。こういった場合、標準SQLでは「"」(二重引用符)で名前を囲むことで使用可能になります。

    この部分にMySQLでは独自仕様があり、標準インストール時の設定である「MySQL構文モード」では、「`」(バックォート)で囲みます。「MySQL構文モード」では、「"」(二重引用符)は、「'」(単一引用符)と同じく文字定数になる点に注意してください。

    <MySQL構文モード>
    select
    'abc' -- 「'」(単一引用符)で囲んだものは、文字定数
    ,"abc" -- 「"」(二重引用符)で囲んだものも、MySQL標準では、文字定数。標準SQLと異なる
    ,`abc` -- 「`」(バッククォート)で囲んだものは、MySQLでは表名、列名などの名前
    from t1

    <MySQLのANSIモード>
    select
    'abc' -- 「'」(単一引用符)で囲んだものは、文字定数
    ,"abc" -- 「"」(二重引用符)で囲んだものは、ANSIモードでは、表名、列名などの名前
    ,`abc` -- 「`」(バッククォート)で囲んだものは、MySQLでは表名、列名などの名前
    from t1



    ここから、具体的な質問への回答です。

    -- 表が存在すれば削除
    drop table if exists `c_mast`;
    drop table if exists `user`;

    -- 表定義
    create table `c_mst`
    ( `cid` int primary key -- キャリアコード
    ,`cname` varchar(30) -- キャリア名
    );
    insert into `c_mst` values
    (1,'pc')
    ,(2,'docomo')
    ,(3,'softbank')
    ,(4,'au')
    ;

    create table `user`
    ( `id` int primary key auto_increment -- 会員id
    ,`name` varchar(30) -- 会員名
    ,`joined` datetime -- 入会日
    ,`carrier` smallint -- キャリア
    );

    -- テストデータ格納
    insert into `user` values
    (null,'a','2009-03-13 01:00:00',(select `cid` from c_mst where cname='pc'))
    ,(null,'b','2009-03-13 01:00:00',(select `cid` from c_mst where cname='docomo'))
    ,(null,'c','2009-03-13 01:00:00',(select `cid` from c_mst where cname='softbank'))
    ,(null,'d','2009-03-13 01:00:00',(select `cid` from c_mst where cname='au'))
    --
    ,(null,'a','2009-03-13 01:00:00',(select `cid` from c_mst where cname='pc'))
    --
    ,(null,'b','2009-03-13 01:00:00',(select `cid` from c_mst where cname='docomo'))
    --
    ,(null,'c','2009-03-13 01:00:00',(select `cid` from c_mst where cname='softbank'))
    --
    ,(null,'d','2009-03-13 01:00:00',(select `cid` from c_mst where cname='au'))
    ;
    --
    insert into `user`
    select null,'e','2009-03-14 12:00:00',`carrier` from `user`;
    insert into `user` values
    (null,'g',current_timestamp,(select `cid` from c_mst where cname='pc'))
    ;

    -- 今日の入会者数
    -- current_dateを使用
    select count(*) as `cnt`
    from `user`
    where date(`joined`)=current_date;

    -- 日付指定
    select count(*) as `cnt`
    from `user`
    where date(`joined`)='2009-03-15';

    -- 昨日の入会者数
    -- current_dateを使用
    select count(*) as `cnt`
    from `user`
    where date(`joined`)=current_date-interval 1 day;

    -- 日付指定
    select count(*) as `cnt`
    from `user`
    where date(`joined`)='2009-03-14';

    -- キャリア別総会員数
    -- キャリア名に変換せず
    select
    `carrier`,count(*) as `cnt`
    from `user`
    group by `carrier`;

    -- キャリア名に変換
    select
    (select `cname` from `c_mst` where `cid`=`carrier`) as `cname`
    ,count(*) as `cnt`
    from `user`
    group by `carrier`;

    -- 入会日の範囲で、キャリア別
    select
    (select `cname` from `c_mst` where `cid`=`carrier`) as `cname`
    ,count(*) as `cnt`
    from `user`
    where date(`joined`) between '2009-03-14' and '2009-03-15'
    group by `carrier`;
  • id:chuken_kenkou
    一部訂正と補足説明。

    <訂正>表名の誤り
    -- 表が存在すれば削除
    drop table if exists `c_mast`;

    drop table if exists `c_mst`;


    <補足説明>

    以下のSQLでは、MySQLの「group by時にselectで指定できる列」の拡張仕様を使っています。

    http://dev.mysql.com/doc/refman/4.1/ja/group-by-hidden-fields.html?ff=nopfpls

    簡単に言うと、標準SQLや殆どのRDBMSでは、group by指定時にselectで指定できるのは
    (1)group byで指定した列
    (2)count、maxなどの集計(集合)関数
    (3)定数
    です。

    MySQLでは、これに加え、group byすることで値が一意になるなら、「group byで指定していない列も指定できる」というものです。ただし、値が一意にならないなら、結果は保証されず、標準インストール時はエラーにもしてくれません。この点には、注意してください。

    <MySQLではok>
    select
    c1,
    c2, -- group byで未指定
    count(*)
    from t1
    group by c1


    直前に提示した、以下のSQLで使っています。

    -- キャリア名に変換
    select
    (select `cname` from `c_mst` where `cid`=`carrier`) as `cname`
    ,count(*) as `cnt`
    from `user`
    group by `carrier`;

    -- 入会日の範囲で、キャリア別
    select
    (select `cname` from `c_mst` where `cid`=`carrier`) as `cname`
    ,count(*) as `cnt`
    from `user`
    where date(`joined`) between '2009-03-14' and '2009-03-15'
    group by `carrier`;
  • id:chuken_kenkou
    再追記。

    group byにcname列を追加することで、MySQLの独自仕様に頼らなくできます。

    -- キャリア名に変換
    select
    (select `cname` from `c_mst` where `cid`=`carrier`) as `cname`
    ,count(*) as `cnt`
    from `user`
    group by `carrier`
    ,`cname`
    ;

    -- 入会日の範囲で、キャリア別
    select
    (select `cname` from `c_mst` where `cid`=`carrier`) as `cname`
    ,count(*) as `cnt`
    from `user`
    where date(`joined`) between '2009-03-14' and '2009-03-15'
    group by `carrier`
    ,`cname`
    ;
  • id:xptree
    chuken_kenkouさん何度もありがとうございました。
    ポイントを送付させて頂きます。

    どなたかポイント送付のやり方を教えて頂いてもよろしいでしょうかm(__)m
  • id:chuken_kenkou
    自分で答えるのも恥ずかしい気がしますが、下記リンクに送付フォームがあります。

    http://www.hatena.ne.jp/help/point


    また、老婆心ながら。。。

    他の方の回答も、それぞれ意味のある内容です。もしできましたら、今後は回答があった後では、キャンセルするのでなく、一旦、その質問を締め、(できましたらそれぞれの方にポイントを配布し、)新たな質問とするようにされれば、より多くの方がより協力してもらえると思います。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません