所以我有一个像这样结构的MySQL表:
CREATE TABLE `spenttime` {
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) NOT NULL,
`serverid` int(11) NOT NULL,
`time` int(11) NOT NULL,
`day` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `dbid_sid_day` (`userid`,`serverid`,`day`)
}
我每天为每个注册玩家存储花在游戏服务器上的时间。 time
是花费的时间(以秒为单位),day
是每天的unix时间戳(当天开始)。我想在我的数据库上创建一个View,它将显示每个用户每周在服务器上花费的时间,但是显示该时间的列,每周独立于每个服务器。例如数据(为了澄清,我将在此示例中使用日期格式Y-M-D而不是day
列的unix时间戳):
INSERT INTO `spenttime` (`userid`, `serverid`, `time`, `day`) VALUES
(1, 1, 200, '2013-04-01'),
(1, 1, 150, '2013-04-02'),
(2, 1, 100, '2013-04-02'),
(3, 1, 500, '2013-04-04'),
(2, 2, 400, '2013-04-04'),
(1, 1, 300, '2013-04-08'),
(3, 1, 200, '2013-04-08');
对于名为spenttime_week
的viev中的数据应该出现:
+--------+----------+--------+------------+------+
| userid | serverid | time | yearweek | rank |
+--------+----------+--------+------------+------+
| 1 | 1 | 350 | '2013-W14' | 2 |
| 2 | 1 | 100 | '2013-W14' | 3 |
| 3 | 1 | 500 | '2013-W14' | 1 |
| 2 | 2 | 400 | '2013-W14' | 1 |
| 1 | 1 | 300 | '2013-W15' | 1 |
| 3 | 1 | 200 | '2013-W15' | 2 |
+--------+----------+--------+------------+------+
我知道如何生成不含排名的视图,我只有排名栏的麻烦...... 我怎样才能做到这一点?
//编辑 另外,这个专栏必须出现在viev中,我无法从该视图中选择生成它,因为我将使用它的app不允许...
答案 0 :(得分:2)
首先,你需要创建第一个VIEW,它将同一周每个用户的花费时间相加:
clients
然后您可以创建视图:
CREATE VIEW total_spent_time AS
SELECT userid,
serverid,
sum(time) AS total_time,
yearweek(day, 3) as week
FROM spenttime
GROUP BY userid, serverid, week;
请查看小提琴here。
答案 1 :(得分:1)
你可以通过很多方式获得一周年专栏,为了清晰起见,这是一个快速懒惰的解决方案(因为我怀疑你正在努力解决这个问题)。但是,你可以在这里获得排名。 使用自联接获取数据集,包括时间值高于当前行的行,然后计算具有更高值的行:
这在MSSQL中要容易得多,这是我99%的时间生活的地方,你可以在那里使用RANK()函数。直到今天我还没有意识到在mysql中没有相应的东西。如果没有MS的帮助,可以找出如何获得相同结果的乐趣。
为上下文准备内容:
CREATE TABLE spenttime (userid int, serverid int, [time] int, [day] DATETIME)
CREATE TABLE weeklookup (weekname VARCHAR(10), weekstart DATETIME, weekend DATETIME)
INSERT INTO spenttime (userid, serverid, [time], [day]) VALUES
(1, 1, 200, '2013-apr-01'),
(1, 1, 150, '2013-apr-02'),
(2, 1, 100, '2013-apr-02'),
(3, 1, 500, '2013-apr-04'),
(2, 2, 400, '2013-apr-04'),
(1, 1, 300, '2013-apr-08'),
(3, 1, 200, '2013-apr-08');
INSERT INTO weeklookup(weekname, weekstart, weekend) VALUES
('2013-w14', '01/apr/2013', '08/apr/2013'),
('2013-w15', '08/apr/2013', '15/apr/2013')
GO
CREATE VIEW weekgroup AS
SELECT a.userid ,
a.serverid ,
a.[time] ,
w1.weekname
FROM spenttime a
INNER JOIN weeklookup w1 ON [day] >= w1.weekstart
AND [day] < w1.weekend
GO
选择视图的语句:
SELECT wv1.userid ,
wv1.serverid ,
wv1.[time] ,
wv1.weekname AS yearweek ,
COUNT(wv2.[time]) + 1 AS rank
FROM weekgroup wv1
LEFT JOIN weekgroup wv2 ON wv1.[time] < wv2.[time]
AND wv1.weekname = wv2.weekname
AND wv1.serverid = wv2.serverid
GROUP BY wv1.userid ,
wv1.serverid ,
wv1.[time] ,
wv1.weekname
ORDER BY wv1.weekname ,
wv1.[time] DESC
答案 2 :(得分:0)
如果要存储排名,可以使用insert
触发器。插入触发器将计算排名,如:
select count(*)
from spenttime_week w
where w.yearweek = new.yearweek and time >= new.time
但是,我不建议这样做,因为你必须创建一个update
触发器,并修改已经插入的等级值。
而是使用SQL访问表,如:
select w.*,
(select count(*) from spenttime_week w2 where w2.yearweek = w.yearweek and w2.time >= w.time
) as rank
from spenttime_week w
此SQL可能会有所不同,具体取决于您希望如何处理数据中的关系。出于性能原因,您的索引应至少为yearweek
,并且可能位于yearweek, time
。