Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/255.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 什么样的mysql查询可以让我从这个表中按月获得聚合的统计数据?_Php_Mysql - Fatal编程技术网

Php 什么样的mysql查询可以让我从这个表中按月获得聚合的统计数据?

Php 什么样的mysql查询可以让我从这个表中按月获得聚合的统计数据?,php,mysql,Php,Mysql,我在我的网站上设置了一个积分系统,每个积分累积都记录在积分表中。结构很简单,p_userid、p_points(在这个动作中累积了多少点)和p_时间戳 我想显示每个月前3名积分累积用户。因此,本质上,它应该为每个用户id汇总当月的p_points表,并显示前3位用户,按月份分组。用户ID将连接到用户表,以获取实际用户名 最好的方法是什么?我使用php/mysql 编辑: 作为一种可能的解决方案,我可以创建另一个列,并将YYYY-MM记录到其中,然后简单地根据该列对其进行分组,但对于一个已经很大的

我在我的网站上设置了一个积分系统,每个积分累积都记录在积分表中。结构很简单,p_userid、p_points(在这个动作中累积了多少点)和p_时间戳

我想显示每个月前3名积分累积用户。因此,本质上,它应该为每个用户id汇总当月的p_points表,并显示前3位用户,按月份分组。用户ID将连接到用户表,以获取实际用户名

最好的方法是什么?我使用php/mysql

编辑: 作为一种可能的解决方案,我可以创建另一个列,并将YYYY-MM记录到其中,然后简单地根据该列对其进行分组,但对于一个已经很大的表,我需要记录更多的数据

编辑2:

以这种方式存储的数据

INSERT INTO `points` (`point_userid`, `point_points`, `point_code`, `point_date`) VALUES
(8465, 20, 3, 1237337627),
(46745, 20, 3, 1237337678),
(7435, 20, 3, 1237337733),
(46565, 20, 3, 1237337802),
(4466, 20, 3, 1237337836),
(34685, 20, 3, 1237337885),
(8544, 20, 3, 1237337908),
(6454, 20, 3, 1237337998),
(45765, 20, 3, 1237338008),
(3476, 20, 3, 1237338076);

这在MySQL中并不容易

首先,您需要创建一个变量表,一个用于存储当前组,另一个用于存储组中的当前行号。将它们都初始化为NULL

然后按月迭代分组,选择按分数排序的所有行,选择当前行数并增加它。如果组发生更改,请将行号重置为1

然后将所有这些放在子选择中,在外部选择中,选择rownumberHm的所有行

太简单了

SELECT COUNT(tb1.p_points) as total_points, tb1.p_userid, tb1.p_timestamp, tb2.username 
FROM tb1, tb2 
WHERE tb1.p_userid = tb2.username AND p_timestamp BETWEEN 'start_of_date' AND 'end_of_month' 
GROUP BY p_userid 
ORDER BY total_points DESC LIMIT 3

语法可能有点过时(对SQL来说相对较新)-通过这样的查询进行迭代不会得到您想要的结果吗?必须承认,Mark的回答让我觉得这肯定太简单了,但我想我还是会让你看看的。

我对plpgsql上瘾,我不知道simmilar是否可以在MySQL中工作,以及PHP将如何获得结果(我不知道多个查询是否会被视为联合),但很少有测试是有希望的

CREATE PROCEDURE topusers(OUT query TEXT) BEGIN
    DECLARE time TIMESTAMP;
    SELECT MIN(CONCAT(EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(p_timestamp)), '01')) INTO time FROM t;
    SET @query = '';
REPEAT
    SET @query = CONCAT(@query, '(SELECT SUM(p_points) as total_points, p_userid, ', UNIX_TIMESTAMP(time), ' 
    FROM t
    WHERE p_timestamp BETWEEN ', UNIX_TIMESTAMP(time), ' AND ', UNIX_TIMESTAMP(ADDDATE(time, INTERVAL 1 MONTH)), ' 
    GROUP BY p_userid 
    ORDER BY total_points DESC LIMIT 3)');
    SELECT ADDDATE(time, INTERVAL 1 MONTH) INTO time;
    IF time < NOW() THEN
        SET @query=CONCAT(@query, ' UNION ');
    END IF;
UNTIL time > NOW() END REPEAT;
    SELECT @query INTO query;
END//
最后呢

DEALLOCATE PREPARE stmt1; 

这将得到它的一个月。。。只要我在php中确定时间戳(很简单),但我需要这是一个循环查询,每个月都会输出结果。我认为这可能有点太简单了:)您可以在mysql中将时间戳缩减为月/年(通过操纵字符串或从UnixtTime返回unix时间),然后按该字段分组。我不确定这会让你走得有多近。这只需要对代码做一个很小的修改。您的列类型是什么?你能发布你的创建脚本和一些我可以用来测试的示例测试数据吗,就像我在回答中所做的那样?
SELECT COUNT(tb1.p_points) as total_points, tb1.p_userid, tb1.p_timestamp, tb2.username 
FROM tb1, tb2 
WHERE tb1.p_userid = tb2.username AND p_timestamp BETWEEN 'start_of_date' AND 'end_of_month' 
GROUP BY p_userid 
ORDER BY total_points DESC LIMIT 3
CREATE PROCEDURE topusers(OUT query TEXT) BEGIN
    DECLARE time TIMESTAMP;
    SELECT MIN(CONCAT(EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(p_timestamp)), '01')) INTO time FROM t;
    SET @query = '';
REPEAT
    SET @query = CONCAT(@query, '(SELECT SUM(p_points) as total_points, p_userid, ', UNIX_TIMESTAMP(time), ' 
    FROM t
    WHERE p_timestamp BETWEEN ', UNIX_TIMESTAMP(time), ' AND ', UNIX_TIMESTAMP(ADDDATE(time, INTERVAL 1 MONTH)), ' 
    GROUP BY p_userid 
    ORDER BY total_points DESC LIMIT 3)');
    SELECT ADDDATE(time, INTERVAL 1 MONTH) INTO time;
    IF time < NOW() THEN
        SET @query=CONCAT(@query, ' UNION ');
    END IF;
UNTIL time > NOW() END REPEAT;
    SELECT @query INTO query;
END//
CALL topusers(@query); PREPARE stmt1 FROM @q; EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;