我想计算特定月份和日期的订阅者数量,并以表格格式打印。我有3个表(注册,registration_session和商品),并希望根据商品表中的注册计算月数和日数的记录数,更新日期限制为30天。我已经给出了解决方案并且它工作正常,但是需要花费大量时间来打印最终结果。
编辑: 我的计划是打印必须发送的整年的短信/语音呼叫详细信息总数。但是不要计算那些超过30天的记录。请检查我下面给出的PHP代码,你可能会理解我想要做什么。它工作但问题是,它很慢。这需要将近一个小时才能完成任务。
最终结果:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
January 17333 15455 15368 16348 14827 15054 14637
February 17332 15481 15400 16351 14824 15059 14613
March 17125 15689 15721 16393 14807 14938 14479
April 18542 17426 17485 17941 16414 16427 15972
May 15824 14870 15044 15441 14311 14485 13861
June 15186 14138 14360 14769 13643 13798 13195
July 13496 12602 12837 13163 12168 12228 11669
August 13305 12333 12570 12891 11913 11974 11422
September 13286 12371 12649 12913 11898 11927 11553
October 12893 11773 11912 12390 11407 11516 11097
November 13563 12415 12516 13042 12028 12173 11764
December 13849 12172 12274 13041 11797 12119 11613
我的问题是,如何让它更快?
我的表: 注册
id mobile name day state language status
1 1234566532 ishtiyaq 'SUN:MON' up en 1
2 2313443454 sandeep 'MON:TUE' up en 1
3 7436343422 shiv 'MON:TUE:WED' up en 1
registration_session
id reg_id session com distt status
1 1 'JAN:FEB' com1:com2:com3 dist1:dist2:dist3 1
2 1 'DEC:JAN:FEB' com1:com2 dist1:dist2 1
3 2 'APR:MAY:JUN' com4:com6 dist4:dist8 1
商品
id state distt com price date_updated
1 up distt1 com1 200 2015-04-23
2 up distt2 com2 420 2015-12-17
3 up distt4 com3 340 2015-10-16
4 up distt1 com2 560 2015-09-13
5 up distt4 com4 320 2015-11-01
6 mp distt5 com2 322 2015-10-01
7 dl distt7 com5 120 2015-12-11
结果:
|--------|---------------|---------------|---------------|---------------|---------------|---------------|---------------|
| | Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday |
|--------|---------------|---------------|---------------|---------------|---------------|---------------|---------------|
|January | 9876-14150 | 8533-12026 | 8491-11991 | 9136-13027 | 8196-11581 | 8404-12015 | 8244-11748 |
|--------|---------------|---------------|---------------|---------------|---------------|---------------|---------------|
|Febury | 9845-13450 | 8521-54026 | 5441-13491 | 1136-13217 | 7196-16531 | 8704-12613 | 2244-14748 |
|--------|---------------|---------------|---------------|---------------|---------------|---------------|---------------|
......
我的解决方案:
$arr_months = array('JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC');
$arr_days = array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT');
foreach ($arr_months as $month) {
foreach ($arr_days as $day) {
$total_msg = 0;
$total_rec = 0;
$sql1 = "SELECT registration.mobile,
registration.id,
registration.state,
registration.language,
registration_session.com,
registration_session.distt
FROM registration_session
INNER JOIN registration
ON registration_session.reg_id = registration.id
WHERE registration_session.session LIKE '%" . $month . "%'
AND registration.status = 1
AND registration.language = 'en'
AND registration.day LIKE '%" . $day . "%'
ORDER BY registration.mobile";
$result1 = mysqli_query($con, $sql1);
while ($row1 = mysqli_fetch_assoc($result1)) {
$state = $row1['state'];
$commodity = explode(':', $row1['commodity']);
$distt = explode(':', $row1['distt']);
$count = count($commodity);
$found = false;
while ($count > 0) {
$sql2 = "SELECT * FROM commodity
WHERE date_updated BETWEEN CURDATE() - INTERVAL 30 DAY AND SYSDATE()
AND state = '".$state."'
AND distt = '".$distt[$count - 1]."'
AND cv_commodity = '".$commodity[$count - 1]."'";
$result2 = mysqli_query($con, $sql2);
if (mysqli_num_rows($result2) > 0) {
$total_msg++;
$found = true;
}
$count--;
}
if ($found == true) {
$total_rec++;
}
}
}
}
--
-- Table structure for table `commodity`
--
CREATE TABLE IF NOT EXISTS `commodity` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`state` varchar(100) NOT NULL,
`distt` varchar(100) NOT NULL,
`com` varchar(100) NOT NULL,
`price` int(10) NOT NULL,
`date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
创建表格声明:
CREATE TABLE IF NOT EXISTS `registration` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`mobile` int(10) DEFAULT NULL,
`name` varchar(22) NOT NULL,
`day` varchar(255) NOT NULL,
`state` varchar(50) NOT NULL,
`language` varchar(2) NOT NULL,
`status` int(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `registration_session` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`reg_id` int(10) DEFAULT NULL,
`session` varchar(255) NOT NULL,
`com` varchar(255) NOT NULL,
`distt` varchar(50) NOT NULL,
`status` int(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `reg_id` (`reg_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `commodity` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`state` varchar(100) NOT NULL,
`distt` varchar(100) NOT NULL,
`com` varchar(100) NOT NULL,
`price` int(10) NOT NULL,
`date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
答案 0 :(得分:0)
如果我正确地读取你的循环,这个脚本会对数据库进行大量调用。第一个查询是工作日*月(84个查询),然后是84个循环中每个循环的状态,商品和分散的所有可能组合。
我建议一次性获取两个查询的所有结果,然后循环遍历PHP中的记录,以按月,日和州,商品和Distt形成结果。
如果你不需要那种级别的谷物,我也会汇总你的查询。在第一个例子中:
SELECT
registration.day,
registration.mobile,
registration.id,
registration.state,
registration.language,
registration_session.com,
registration_session.session,
registration_session.distt,
COUNT(1) AS cnt
FROM
registration_session
INNER JOIN
registration ON registration_session.reg_id = registration.id
WHERE
AND registration.status = 1
AND registration.language = 'en'
GROUP BY
registration.day,
registration.mobile,
registration.id,
registration.state,
registration.language,
registration_session.com,
registration_session.session,
registration_session.distt
商品一:
SELECT
state,
distt,
cv_commodity,
COUNT(1) AS cnt
FROM
commodity
WHERE
date_updated BETWEEN CURDATE() - INTERVAL 30 DAY AND SYSDATE()
GROUP BY
state,
distt,
cv_commodity
然后在结果中执行PHP循环:
$arr_months = array('JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC');
$arr_days = array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT');
foreach ($arr_months as $month) {
foreach ($arr_days as $day) {
$total_msg = 0;
$total_rec = 0;
foreach ($result1 AS $row1) {
if (strpos($row1['session'],$month) !== false AND strpos($row1['day'],$day) !== false){
$state = $row1['state'];
$commodity = explode(':', $row1['com']);
$distt = explode(':', $row1['distt']);
#$count = number of commodities * number of records in db for this row
$count = count($commodity) * $row1['cnt'];
#Check if State/Commodity exist in $result2 using the same strpos method above
#Store aggregates for each month/day in a new array to display results
}
}
}
}
这是我通过减少数据库查询数量来优化性能的方法,汇总结果,因此需要预先将更少的记录加载到内存中,然后循环以获取结果。