ヒットを保存します。私のテーブルは次のようになります:
_ ID | time | Country
--------------------------------
1 | 01:00:00 | France
2 | 01:00:00 | France
3 | 01:00:00 | Brazil
4 | 01:00:00 | USA
5 | 02:00:00 | USA
_
これは私のクエリです:
_SELECT COUNT(*) as total_hits, HOUR(time) as hour, Country
FROM hits
WHERE time >= CURDATE()
GROUP BY HOUR(time)
_
取得したヒット数を数え、時間ごとにグループ化します。
_ time | total_hits
---------------------------
01:00:00 | 4
02:00:00 | 1
_
time
列でグループ化された1つの結果とcountries
列でグループ化された別の結果が必要です。これは私が必要なものです:
1)このように時間ごとにグループ化(上記と同じ)
_ time | total_hits
---------------------------
01:00:00 | 4
02:00:00 | 1
_
2)このような国でグループ化されたAND
_ country | total_hits
---------------------------
France | 2
USA | 2
Brazil | 1
_
私はそれをできた:
_SELECT
COUNT(*)
, HOUR(time)
, COUNT(IF( Country = 'France', Country, null)) AS France
, COUNT(IF( Country = 'USA', Country, null)) AS USA
, COUNT(IF( Country = 'Brazil', Country, null)) AS Brazil
FROM hits
WHERE time >= CURDATE()
GROUP BY HOUR(time)
_
または、代わりにCASE
またはSUM(Country = 'France') AS France
を使用します。
ただし、国の列には3か国以上があります。すべての国でこれを行うと、私のクエリは非常に長くなります。
私はこれを行うことができます:
_SELECT COUNT(*), Country, HOUR(time)
FROM hits
WHERE time >= CURDATE()
GROUP BY Country, HOUR(time)
_
しかし、出力は次のようになります。
_ time | country | total_hits
---------------------------------------
01:00:00 | France | 2
01:00:00 | USA | 1
01:00:00 | Brazil | 1
02:00:00 | USA | 1
_
ただし、上記のような出力が必要です。
だから基本的に私はこれらのクエリを1つのクエリで必要とします:
1)HOURでグループ化(上記と同じ)
_SELECT COUNT(*) as total_hits, HOUR(time) as hour, Country
FROM hits
WHERE time >= CURDATE()
GROUP BY HOUR(time)
_
2)AND国によるグループ化
_SELECT COUNT(*) as total_hits
FROM hits
WHERE time >= CURDATE()
GROUP BY Country
_
パフォーマンスは重要です。データベースには数百万のエントリがあります。たぶん、MySQLはこの問題の最善の方法ではありませんか?
書式設定のお手伝いはできないと思いますが、必要なクエリは次のとおりです。
SELECT
IFNULL(Hour,CONCAT('Total for ',IFNULL(Country,'All Countries'))) Statistic,
COUNT(1) TotalHits
FROM
(
SELECT Country,(time - INTERVAL MOD(UNIX_TIMESTAMP(time),3600) SECOND) Hour
FROM hits WHERE time >= (DATE(NOW()) + INTERVAL 0 SECOND)
) AA
GROUP BY Country,Hour WITH ROLLUP;
USE test
DROP TABLE IF EXISTS hits;
CREATE TABLE hits
(
id int not null auto_increment,
time datetime,
country varchar(20),
PRIMARY KEY (id)
);
INSERT INTO hits (time,Country) VALUES
('2014-06-19 01:00:00','France'),
('2014-06-19 01:00:00','Brazil'),
('2014-06-19 01:00:00','USA'),
('2014-06-19 02:00:00','USA');
mysql> USE test
Database changed
mysql> DROP TABLE IF EXISTS hits;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE hits
-> (
-> id int not null auto_increment,
-> time datetime,
-> country varchar(20),
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO hits (time,Country) VALUES
-> ('2014-06-19 01:00:00','France'),
-> ('2014-06-19 01:00:00','Brazil'),
-> ('2014-06-19 01:00:00','USA'),
-> ('2014-06-19 02:00:00','USA');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM hits;
+----+---------------------+---------+
| id | time | country |
+----+---------------------+---------+
| 1 | 2014-06-19 01:00:00 | France |
| 2 | 2014-06-19 01:00:00 | Brazil |
| 3 | 2014-06-19 01:00:00 | USA |
| 4 | 2014-06-19 02:00:00 | USA |
+----+---------------------+---------+
4 rows in set (0.00 sec)
mysql>
mysql> SELECT
-> IFNULL(Hour,CONCAT('Total for ',IFNULL(Country,'All Countries'))) Statistic,
-> COUNT(1) TotalHits
-> FROM
-> (
-> SELECT Country,(time - INTERVAL MOD(UNIX_TIMESTAMP(time),3600) SECOND) Hour
-> FROM hits WHERE time >= (DATE(NOW()) + INTERVAL 0 SECOND)
-> ) AA
-> GROUP BY Country,Hour WITH ROLLUP;
+-------------------------+-----------+
| Statistic | TotalHits |
+-------------------------+-----------+
| 2014-06-19 01:00:00 | 1 |
| Total for Brazil | 1 |
| 2014-06-19 01:00:00 | 1 |
| Total for France | 1 |
| 2014-06-19 01:00:00 | 1 |
| 2014-06-19 02:00:00 | 1 |
| Total for USA | 2 |
| Total for All Countries | 4 |
+-------------------------+-----------+
8 rows in set (0.00 sec)
mysql>
警告:テーブルに時間インデックスがあることを確認してください
ALTER TABLE hits ADD INDEX time_index (time);
追加のクエリは
SELECT
IFNULL(Country,CONCAT('Total for ',IFNULL(Hour,DATE(NOW())))) Statistic,
COUNT(1) TotalHits
FROM
(
SELECT Country,(time - INTERVAL MOD(UNIX_TIMESTAMP(time),3600) SECOND) Hour
FROM hits WHERE time >= (DATE(NOW()) + INTERVAL 0 SECOND)
) AA
GROUP BY Hour,Country WITH ROLLUP;
その出力は
+-------------------------------+-----------+
| Statistic | TotalHits |
+-------------------------------+-----------+
| Brazil | 1 |
| France | 1 |
| USA | 1 |
| Total for 2014-06-19 01:00:00 | 3 |
| USA | 1 |
| Total for 2014-06-19 02:00:00 | 1 |
| Total for 2014-06-19 | 4 |
+-------------------------------+-----------+
7 rows in set (0.00 sec)
おそらく、UNIONと組み合わせた2つのクエリはあなたのために働くでしょう
SELECT
IFNULL(Country,CONCAT('Total for ',IFNULL(Hour,DATE(NOW())))) Statistic,
COUNT(1) TotalHits
FROM
(
SELECT Country,(time - INTERVAL MOD(UNIX_TIMESTAMP(time),3600) SECOND) Hour
FROM hits WHERE time >= (DATE(NOW()) + INTERVAL 0 SECOND)
) AA
GROUP BY Hour,Country
UNION
SELECT
IFNULL(Hour,CONCAT('Total for ',IFNULL(Country,'All Countries'))) Statistic,
COUNT(1) TotalHits
FROM
(
SELECT Country,(time - INTERVAL MOD(UNIX_TIMESTAMP(time),3600) SECOND) Hour
FROM hits WHERE time >= (DATE(NOW()) + INTERVAL 0 SECOND)
) AA
GROUP BY Country,Hour WITH ROLLUP;
最初のWITH ROLLUP
を削除して、合計が1回になるようにしました