草庐IT

php - 根据用户订阅计算月和日的记录

coder 2023-10-26 原文

我想计算特定月份和日期的订阅者数量,并以表格格式打印。我有 3 个表(registration、registration_session 和 commodity),我想根据更新日期限制为 30 天的商品表中的注册来统计月和日的记录数。我已经给出了解决方案,它工作正常,但打印最终结果需要很多时间。

编辑: 我的计划是打印全年必须发送的 SMS/语音调用详细信息的总数。但不要计算超过 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 ;

最佳答案

如果我没看错你的循环,这个脚本就会对数据库进行大量调用。第一个查询是 weekdays * months(84 个查询),然后是这 84 个循环中每个循环的状态、商品和 distt 的所有可能组合。

我建议一次获取两个查询的所有结果,然后循环遍历 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
        }
    }
}
}

我会采用这种方法来优化性能,方法是减少数据库查询的数量,汇总结果,从而减少需要预先加载到内存中的记录,然后循环获取我的结果。

关于php - 根据用户订阅计算月和日的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34559239/

有关php - 根据用户订阅计算月和日的记录的更多相关文章

  1. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  2. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  5. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  6. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

    我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

  7. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  8. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  9. ruby - 如何根据长度将路径数组转换为嵌套数组或散列 - 2

    我需要根据字符串路径的长度将字符串路径数组转换为符号、哈希和数组的数组给定以下数组:array=["info","services","about/company","about/history/part1","about/history/part2"]我想生成以下输出,对不同级别进行分组,根据级别的结构混合使用符号和对象。产生以下输出:[:info,:services,about:[:company,history:[:part1,:part2]]]#altsyntax[:info,:services,{:about=>[:company,{:history=>[:part1,:pa

  10. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

随机推荐