我有两个表players
和games
,创建如下:
CREATE TABLE IF NOT EXISTS `players` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `games` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`player` int(11) NOT NULL,
`played_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
我希望每天提取3个值:
因此,假设玩家表格如下所示:
+----+--------+---------------------+
| id | name | created_at |
+----+--------+---------------------+
| 1 | Alan | 2016-02-01 00:00:00 |
| 2 | Benny | 2016-02-01 06:00:00 |
| 3 | Calvin | 2016-02-02 00:00:00 |
| 4 | Dan | 2016-02-03 00:00:00 |
+----+--------+---------------------+
游戏表如下:
+----+--------+---------------------+
| id | player | played_at |
+----+--------+---------------------+
| 1 | 1 | 2016-02-01 01:00:00 |
| 2 | 3 | 2016-02-02 02:00:00 |
| 3 | 2 | 2016-02-03 14:00:00 |
| 4 | 3 | 2016-02-03 17:00:00 |
| 5 | 3 | 2016-02-03 18:00:00 |
+----+--------+---------------------+
然后查询应返回类似
的内容+------------+-----+--------+-------+
| day | new | played | first |
+------------+-----+--------+-------+
| 2016-02-01 | 2 | 1 | 1 |
| 2016-02-02 | 1 | 1 | 1 |
| 2016-02-03 | 1 | 2 | 1 |
+------------+-----+--------+-------+
我有一个解决方案1( new ):
SELECT Date(created_at) AS day,
Count(*) AS new
FROM players
GROUP BY day;
这很容易。我想我也有2个解决方案(播放),感谢MySQL COUNT DISTINCT:
select Date(played_at) AS day,
Count(Distinct player) AS played
FROM games
GROUP BY day;
但我不知道如何获得3( first )所需的结果。我也不知道如何将所有内容放在一个查询中,以节省执行时间(games
表可能包含数百万条记录)。
如果您需要,这是一个插入示例数据的查询:
INSERT INTO `players` (`id`, `name`, `created_at`) VALUES
(1, 'Alan', '2016-02-01 00:00:00'),
(2, 'Benny', '2016-02-01 06:00:00'),
(3, 'Calvin', '2016-02-02 00:00:00'),
(4, 'Dan', '2016-02-03 00:00:00');
INSERT INTO `games` (`id`, `player`, `played_at`) VALUES
(1, 1, '2016-02-01 01:00:00'),
(2, 3, '2016-02-02 02:00:00'),
(3, 2, '2016-02-03 14:00:00'),
(4, 3, '2016-02-03 17:00:00'),
(5, 3, '2016-02-03 18:00:00');
答案 0 :(得分:4)
一个版本是将所有相关数据导入联合并从那里进行分析;
SELECT SUM(type='P') new,
COUNT(DISTINCT CASE WHEN type='G' THEN pid END) played,
SUM(type='F') first
FROM (
SELECT id pid, DATE(created_at) date, 'P' type FROM players
UNION ALL
SELECT player, DATE(played_at) date, 'G' FROM games
UNION ALL
SELECT player, MIN(DATE(played_at)), 'F' FROM games GROUP BY player
) z
GROUP BY date;
在工会中;
类型为P
的记录是玩家创建统计信息
类型为G
的记录是与玩家相关的游戏统计数据
类型为F
的记录是玩家第一次玩游戏时的统计数据。
答案 1 :(得分:2)
您可以根据min(playing_at)计算临时表的结果,并通过
进行过滤select count(player) from
( select player, min(played_at)
from games
group by player
having min(played_at) = YOUR_GIVEN_DATE ) as t;
答案 2 :(得分:1)
此查询将为您提供结果:
select day,( select count(distinct(id)) from players where Date(created_at) = temp.day ) as no_created_at ,
( select count(distinct(player)) from games where Date(played_at) = temp.day) as no_played_at,
( select count(distinct(player)) from games where Date(played_at) =
(select min(Date(played_at)) from games internal_games
where internal_games.player =games.player and Date(games.played_at) = temp.day )) as no_first_played_at
from (
SELECT Date(created_at) AS day
FROM players
GROUP BY day
union
select Date(played_at) AS day
FROM games
GROUP BY day) temp
和输出:
答案 3 :(得分:1)
这是一个带有一堆子查询的解决方案,它解释了玩家可能在没有游戏的情况下创建的可能性,反之亦然:
select
all_dates.date as day,
ifnull(new.num, 0) as new,
ifnull(players.num, 0) as players,
ifnull(first.num, 0) as first
from (
select date(created_at) as date from players
union
select date(played_at) from games
) as all_dates
left join (
select date(created_at) as created_at_date, count(*) as num
from players
group by created_at_date
) as new on all_dates.date = new.created_at_date
left join (
select date(played_at) as played_at_date, count(distinct player) as num
from games
group by played_at_date
) as players on all_dates.date = players.played_at_date
left join (
select min_date, count(*) num
from (
select player, date(min(played_at)) as min_date
from games
group by player
) as players_first
group by min_date
) as first on all_dates.date = first.min_date
order by day;