根据用户订阅计算月份和日期

时间:2016-01-01 19:21:05

标签: php mysql

我想计算特定月份和日期的订阅者数量,并以表格格式打印。我有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 ;

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
        }
    }
}
}

这是我通过减少数据库查询数量来优化性能的方法,汇总结果,因此需要预先将更少的记录加载到内存中,然后循环以获取结果。