簡単なテーブルの集計方法

このQ&Aのポイント
  • 3つのテーブルから指定したユーザーの指定月のアクセス日時と売上げ金額を集計する方法を解説します。
  • SELECT文を使用して、ユーザー情報テーブル、アクセスログテーブル、売上げ金額テーブルを結合し、指定したユーザーの指定月のアクセス数と売上げ金額を取得します。
  • 集計結果の表は、id、username、date、access、salesの5つのカラムで構成されます。
回答を見る
  • ベストアンサー

助けて>< 3つのテーブルで簡単な集計

下記のような3種類のテーブルがあります。 これを集計して、指定したユーザーの指定月のアクセス日時と売上げ金額を表にしたいと思っています。 こんな感じに。 +--+--------+----------+-------+-----+ | id | username| date   | access | sales | +--+--------+----------+-------+-----+ | 1 | admin | 2010-11-13 |   2 | 5000 | | 1 | admin | 2010-11-14 |   2 | 5000 | | 1 | admin | 2010-11-15 |  1 | 20000 | +--+--------+----------+-------+-----+ SELECT u.id AS id, u.username, DATE(a.created_at) AS date, COUNT(*) AS access, SUM(s.amount) AS sales FROM sf_guard_user u INNER JOIN sales s ON u.username = s.user_id LEFT JOIN access_log a ON u.username = a.user_id WHERE (u.username = 'admin' AND a.created_at > '2010-11-01 00:00:00' AND a.created_at < '2010-11-30 23:59:59') GROUP BY date ORDER BY a.created_at; とやってみたのですがダメでした;; ■ユーザー情報テーブル mysql> select id,username from user; +--+---------+ | id | username | +--+---------+ | 1 | admin   | +--+---------+ ■アクセスログテーブル mysql> select * from access_log; +--+-------+--------+------------------+ | id | user_id | ip     | created_at      | +--+-------+--------+------------------+ | 1 | admin  | 127.0.0.1 | 2010-11-13 21:56:54 | | 2 | admin  | 127.0.0.1 | 2010-11-13 21:56:54 | | 3 | admin  | 127.0.0.1 | 2010-11-14 21:56:54 | | 4 | admin  | 127.0.0.1 | 2010-11-14 21:56:54 | | 5 | admin  | 127.0.0.1 | 2010-11-15 21:56:54 | +--+-------+--------+------------------+ ■売上げ金額テーブル mysql> select * from sales; +--+-------+------+------------------+ | id | user_id | amount| created_at      | +--+-------+------+------------------+ | 1 | admin  |  5000 | 2010-11-13 21:56:54 | | 2 | admin  |  5000 | 2010-11-14 21:56:54 | | 3 | admin  |  5000 | 2010-11-15 21:56:54 | | 4 | admin  |  5000 | 2010-11-15 21:56:54 | +--+-------+------+------------------+

  • MySQL
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • yuu_x
  • ベストアンサー率52% (106/202)
回答No.4

SELECT s.user_id AS id ,username ,a.ip ,a.`date` ,access ,sales FROM ( SELECT user_id ,ip ,COUNT(ip) AS access ,DATE(created_at) AS `date` FROM access_log WHERE YEAR(created_at)=2010 AND MONTH(created_at)=11 GROUP BY user_id, `date`, ip ) AS a LEFT JOIN ( SELECT user_id ,SUM(amount) AS sales ,DATE(created_at) AS `date` FROM sales WHERE YEAR(created_at)=2010 AND MONTH(created_at)=11 GROUP BY user_id, `date` ) AS s ON a.user_id=s.user_id AND a.`date`=s.`date` JOIN user AS u ON a.user_id=u.id view 作ってしまいたい気分だ。 何か引っかかるけどまぁいい。アクセスとセールスっておそらく一連の流れだから、まとめてしまってもいんじゃない。

その他の回答 (3)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

>10000円ですね で、よければたとえばこんな感じでいけます。 (元テーブルの正規化が微妙な気がしますが) select user.id , user.username, sub1.date , access , sales from( select user_id,date(created_at) as date ,count(*) as access from access_log group by user_id,date) as sub1 inner join ( select user_id,date(created_at) as date ,sum(amount) as sales from sales group by user_id,date ) as sub2 on sub1.user_id=sub2.user_id and sub1.date=sub2.date inner join user on user.username=sub1.user_id WHERE user.username = 'admin' AND sub1.date between '2010-11-01' AND '2010-11-30'

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

11/15の売り上げはなぜ20000円なのでしょう?

nichansaitama
質問者

お礼

間違えでした、10000円ですね^^;

  • t-ka
  • ベストアンサー率28% (14/50)
回答No.1

DATETIME型をCASTかCONVERT・・でDATE型もしくは文字列型などに適宜変換する。 (2010-11-13 21:56:54)を(2010-11-13)の様に 例えば CAST(created_at,DATE) AS aaa_time など       SELECT , , GROUP BY CAST( , ) AS ex1 FROM access_log       SELECT , , CAST( , ) AS ex2 FROM sales 結合する。 JOIN ・・・ ON access_log.ex1 = sales.ex2   

nichansaitama
質問者

お礼

省略されててよく分からないんですけど、1つのSQL文じゃ難しいんでしょうか? どうやって記述するんでしょうか? また、言い忘れましたがアクセスや売上げの無い日付も存在します。 対応できますでしょうか?

関連するQ&A

  • SQLで、アクセス集計について困っています。

    アクセス集計について困っています。 mysql> desc access_log; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | user_id | varchar(50) | YES | | NULL | | | ip | varchar(15) | YES | | NULL | | | created_at | datetime | NO | | NULL | | | updated_at | datetime | NO | | NULL | | +------------+-------------+------+-----+---------+----------------+ 5 rows in set (0.02 sec) mysql> select * from access_log; +----+---------+-----------+---------------------+---------------------+ | id | user_id | ip | created_at | updated_at | +----+---------+-----------+---------------------+---------------------+ | 1 | admin | 127.0.0.1 | 2010-11-13 21:56:54 | 2010-11-13 23:07:27 | | 2 | admin | 127.0.0.1 | 2010-11-13 21:56:54 | 2010-11-13 23:07:27 | | 3 | admin | 127.0.0.1 | 2010-11-14 21:56:54 | 2010-11-13 23:07:27 | | 4 | admin | 127.0.0.1 | 2010-11-14 21:56:54 | 2010-11-13 23:07:27 | | 5 | admin | 127.0.0.1 | 2010-11-15 21:56:54 | 2010-11-13 23:07:27 | +----+---------+-----------+---------------------+---------------------+ 5 rows in set (0.00 sec) 上記のように定義したテーブルがあります。 SELECT a.id, a.user_id, COUNT(*), DATE(a.created_at) AS date FROM access_log a WHERE (a.user_id = 'admin' AND a.created_at > '2010-11-01 00:00:00' AND a.created_at < '2010-11-29 23:59:59') GROUP BY date ORDER BY a.created_at; のようにして日別のアクセス数の集計をしています。 ここから、同じ日の同一IPのアクセスは1アクセスとして計算したいのですが、 どのようにSQLを書けばよいでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • select構文について

    テーブルを結合して各カラムを出力したいのですが、両方のテーブルに同じカラム名があった場合どのように処理したら言いのでしょうか? 次のようにやってみたのですが、テーブル名をASで置き換えるとうまくいかないのでしょうか。 $rs = mysql_query("select u.name,a.name, from user AS u LEFT JOIN address AS a ON u.id=a.id ;",$conn); while($rec = mysql_fetch_array($rs, MYSQL_ASSOC)){ $username = $rec['u.name']; $officename = $rec['a.name']; echo '$username'; echo '$officename';

    • ベストアンサー
    • MySQL
  • 2テーブルが同じユーザテーブル参照するときの結合

    2つのテーブルで、同じユーザテーブルを参照してデータ取得したいのですが、 どうやって結合すれば良いのでしょうか? ■概要 ・ユーザがアクションに挑戦すると、結果を表示 ・その際、「アクション作成者」と「アクション挑戦者(ユーザ)」を表示したい ※「作成者」「挑戦者」は、同じ「user」テーブルで管理したい ■3テーブル ・「result」「action」「user」 ・「result」「action」テーブルには、それぞれ「user_id」カラムがある ・「result」テーブルには、「action_id」カラムがある。1対多? ■知りたいこと ・一気にまとめて一覧として取得する方法 ・最終的に「結果」と、「result」「action」それぞれに対応した「user」テーブルの「name」カラムを取得したい ■試してみたこと ・これだと「挑戦者名」が取得できない       SELECT *        FROM result r         LEFT JOIN `action` a ON r.`action_id` = a.`id`         LEFT JOIN `user` u ON r.`user_id` = u.`id` ・これだと「挑戦者」のユーザIDしか取得できない       SELECT *,a.user_id AS actionuser_id        FROM result r         LEFT JOIN `action` a ON r.`action_id` = a.`id`         LEFT JOIN `user` u ON a.`user_id` = u.`id`

    • ベストアンサー
    • MySQL
  • MySQL: 複数テーブルのcount

    複数テーブルの総行数(count値)を取得したいのですが、下記だとテーブルA,B,Cの結果が バラバラに出力されてしまいます。 【入力条件】 mysql> select COUNT(*) AS 列ID from テーブルA      union all      select COUNT(*) AS 列ID from テーブルB      union all      select COUNT(*) AS 列ID from テーブルC; 【出力結果】       +-----+       | 列_ID |       +-----+       |  1  | ←テーブルAの合計:行数       |  2  | ←テーブルBの合計:行数       |  3  | ←テーブルCの合計:行数       +-----+ 総行数:6を一発で取得するには、どのようにしたらよろしいのでしょうか? 大変恐縮ですが、ご教授よろしくお願いいたいます。 <<MySQLのverは5,5です。

    • ベストアンサー
    • MySQL
  • 3つのテーブルの処理について

    下記のようなテーブルがあったとして、 テーブルAを基準に考えたいのですが、、、、 テーブルAに付加する形でテーブルBのデータのidカウント数が最も少なく、idが同じもの中でdate日が一番新しいデータを表示し、古いものから並べかえかつテーブルCにidがあるものは一番最後にくるという風に並べかえたいのですが、無理でしょうか? 現在下記のようなSQLを考えていますが、うまくいかないです。。 select * from A left join(select id,case when count(id)=0 then 0 else count(id) end AS cnt FROM B group by id order by date) as b on A.id=b.id left join(select id from C) as c on A.id=c.id order by c.id desc,b.cnt; エラー↓ in the GROUP BY clause or be used in an aggregate function テーブルA id | name | comment| 1 あ   おい 2 い   えい 3 か   テス テーブルB id | event | date | 1 test1 2005/1/4 2 test1 2005/1/4 1 test2 2005/3/4 2 test2 2005/3/4 1 test3 2005/5/4 テーブルC id | 1 理想の結合データ id | name | comment| cnt | date | 3 か   テス 0    2 い   えい 2  2005/3/4  1 あ   おい 3 2005/5/4

  • テーブルの集計+結合

    MySQL+ PHPについて質問です。 商品リスト(テーブルA)から、商品名で関連付けられたユーザー評価(テーブルB)があったとします。 ユーザーが商品ページから評価を5段階でを入れれるようにしました。 商品一覧のページで商品リスト(テーブルA)を表示させ さらにユーザー評価の平均を一緒にテーブルAの商品名から関連付けるように表示させたいのですが、どうやったらいいのでしょうか。 イメージは下記の通りです。 --------------------------------------------------------------- 商品名(テーブルA) ∥ 商品説明(テーブルA) ∥ 商品ランク(テーブルB) --------------------------------------------------------------- オレンジ | おいしい | 評価5 --------------------------------------------------------------- りんご | おいしい | 評価4 --------------------------------------------------------------- 試したSQL文は以下の通りです。 "SELECT title, avg(rank) as avgrank FROM テーブルB group by title join テーブルA テーブルA .title = テーブルB.title"; 残念ながらエラーなのですが、正しくはどう書くのでしょうか。 単純にユーザーが1人であればそのまま結合できるのですが、同じタイトルのものの評価を平均しないといけないため、頭がおかしくなりそうです。

  • 複数テーブルの集計その2

    お世話になります。 先日テーブルの集計について教えていただき、下記集計結果を取得することができたのですが、 新たに自由形50~平泳ぎ50までの合計を追加したいのです。(一人で4種目参加する場合は4と数える) テーブル1 AreaID   AreaName --------------------- 1 北海道 2 東北 テーブル3 ID AreaID   Name  Item1   Item2  Item3 Item4 --------------------------------------------------------- 1   2    鈴木    2    1    4     3 2   1    田中    1    2    null   null 3   2    伊藤    3    null   2    4  「集計結果」       参加人数 自由形50 自由形100 背泳ぎ50 平泳ぎ50  追加部分 --------------------------------------------------------------- 北海道     1     1       1      0      0       2 東北      2     1       2      2      2       7   $sql="select AreaName, count(distinct ID) 参加人数, count(case when Item=1 then 1 else null end) as 自由形50, ・・・略 from t1 as x left join (select ID,AreaID,1 as Item from t3 where Item1=1 or Item2=1 or Item3=1 or Item4=1 union all select ID,AreaID,2 as Item from t3 where Item1=2 or Item2=2 or Item3=2 or Item4=2 ) as y on x.AreaID=y.AreaID group by AreaName order by x.AreaID というようにおしえていただきました。 null以外を取得するSQLをカウントとselectに追加すればいいのかと思い試したのですが期待した値を取得できません。 count(case when Item=AAA then 1 else null end) as abc,と union all select ID,AreaID,AAA as Item from テーブル3 where ItemID1<>'' or ItemID2<>'' or ItemID3<>'' or ItemID4<>'' or (ItemID1<>'' and ItemID2<>'') ・・・ バージョンはMySQL4.1.18です。 よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • テーブルの差分を抽出したいのですが。。。

    mysqlでUSER_TABLとUSER_CHK_TABL一致しないデータ全てを出力したいのですがmysqlだと『NOT EXISTS』が使えないので困ってます。 TABLE構造はUSER_TABLとUSER_CHK_TABLも下記です。 create table USER_TABL (USERNAME varchar(255),MAIL_ADDRESS varchar(255)); oracleならこんな感じかと思ったのですが。。。 select * from USER_TABL where NOT EXISTS (select * from USER_CHK_TABL)

    • ベストアンサー
    • MySQL
  • MySQLでの集計

    いつもお世話になっております。MySQLを利用しておりまして質問です。 同じ構成のテーブルが5つあり、選択されたテーブルを集計するSQLを作成しています。 カラムを簡単に構成を書くと ID、名前、ステータス1、ステータス2 のような形です。 テーブル1、2、3が選択された場合 テーブル1と2でIDの重複のない一覧を作成し、IDが被っていた場合はステータスをそれぞれ大きいほうを保持するようにします。 そして次にテーブル1、2を合わせたテーブルとテーブル3で同じように集計をしたいのですが、ここがうまく出来ません。 実際の環境ではなく簡素化したものなのでおかしな点があるかもしれませんがこのようになっています。 SELECT TTT1.id,TTT1.名前,TTT1.st1,TTT1.st2 FROM(     SELECT id,名前,ステータス1 as st1,ステータス2 as st2     FROM(        SELECT *        FROM テーブル1 T1        WHERE T1.id NOT IN(SELECT T2.id FROM テーブル2 T2)        UNION All        SELECT *        FROM テーブル2 T2        WHERE T2.id NOT IN(SELECT T1.id FROM テーブル T1)     ) as TT1     UNION     SELECT id,名前,st1,st2     FROM(         SELECT T1.id,T1.名前,         (CASE T1.ステータス1 or T2.ステータス1 WHEN "2" THEN "2" WHEN "1" THEN "1" WHEN "0" THEN "0" ELSE null END) as st1,         (CASE T1.ステータス2 or T2.ステータス2 WHEN "2" THEN "2" WHEN "1" THEN "1" WHEN "0" THEN "0" ELSE null END) as st2,         FROM テーブル1 T1,テーブル2 T2         WHERE T1.id = T2.id AND NOT(T1.st1 IS null AND T1.st2 IS null AND T2.st1 IS null AND T2.st2 IS null) ) as TT2 )as TTT1 /* UNION ALL SELECT id,名前,st1,st2 FROM (TTT1とテーブル3を比較したもの)as TTT2 */ /**/で囲ったところでTTT1が呼び出せれば、テーブル1のところをTTT1にし、テーブル2をテーブル3にすれば出来ると思うのですが、そういうことは無理なのでしょうか? また集計するテーブルの数が不特定なので一つずつ集計をする形を取りましたが、 もっとこういう風にやればいいと言う方法はございますでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • MySQL 可変テーブルの集計方法

    今現在、PHP MySQLにてDB&簡単なCMSを作成中です。 仕入テーブル(id, date_y, date_m, id_cost, price, etc...)と勘定項目テーブル(id_cost, name_cost)をid_costをキーにして連結し、月々の勘定項目ごとの集計画面を作成したいのです。 SELECT 仕入テーブル.date_y, 仕入テーブル.date_m, 仕入テーブル.id_direct_cost, 勘定項目テーブル.name_cost, SUM(仕入テーブル.price) AS sumcost FROM 仕入テーブル NATURAL JOIN 勘定項目テーブル WHERE 仕入テーブル.date_y="'.$y.'" AND 仕入テーブル.date_m="'.$m.'" AND 仕入テーブル.typecost="direct" AND 仕入テーブル.id_direct_cost=勘定項目テーブル.id_cost ※$y, $mは集計画面で選択された年月です。 とすると、月々の合計が抽出され、勘定項目ごとの集計ができません。 当方、半年くらい学校にてPHP MySQLを習ったのですが、まだまだ未熟者のため解決できません。 お力をお貸しいただけますと大変ありがたく存じます。 どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL