简体   繁体   English

如何防止PHP中另一个foreach循环内的foreach循环重复?

[英]How to prevent duplicates on a foreach loop inside another foreach loop in PHP?

I have a music website where each time a user click on play, my PHP function insert into table views 我有一个音乐网站,每次用户单击播放时,我的PHP函数就会插入表格views

I'm trying to reorder my MySQL database to optimize it in performance, so I tried in this example to count the total of views for each track grouped by time. 我试图对MySQL数据库进行重新排序以优化其性能,因此在此示例中,我尝试按时间对每个track的视图总数进行计数。

Select only tracks that are in table views : 仅选择表格views轨道:

$query = "SELECT  `track` FROM  `views` GROUP BY `track`";

The result for $query : $query的结果:

|track|
|-----|
|140  |
|125  |
|33   |
|...  |

Count the number of rows for each result as plays and group by date: 计算每个结果作为播放的行数,并按日期分组:

$querysel = $this->db->query(sprintf("SELECT COUNT( * ) AS plays , `time`, `track` FROM `views` WHERE `track` = '%s' GROUP BY DATE( `time` )", $tid)); 

The result for $querysel $querysel的结果

|plays |time                |track |
|------|--------------------|------|
|82    |2016-12-26 18:20:16 |140   |
|1     |2017-01-10 15:52:55 |140   |
|2     |2017-01-26 13:17:25 |140   |

Final insert in a new table the result: 最后在新表中插入结果:

$this->db->query(sprintf("INSERT INTO views_counts (tid,plays,time) VALUES ('%s','%s','%s')", $newtid, $plays, $time));

Here is my complete function: 这是我的完整功能:

function countViews() {

    $query = "SELECT  `track` FROM  `views` GROUP BY `track`";
    $result = $this->db->query($query);

    while($row = $result->fetch_assoc()) {
        $rows[] = $row;
    }

    foreach($rows as $row) {
        $tid = $row['track'];

        $querysel = $this->db->query(sprintf("SELECT COUNT( * ) AS plays , `time`, `track` FROM `views` WHERE `track` = '%s' GROUP BY DATE( `time` )", $tid)); 

        while($rownew = $querysel->fetch_assoc()) {
            $rowsnew[] = $rownew;
        }

        foreach($rowsnew as $rownew) {

            $newtid = $rownew['track'];
            $plays = $rownew['plays'];
            $time = $rownew['time'];

            $this->db->query(sprintf("INSERT INTO views_counts (tid,plays,time) VALUES ('%s','%s','%s')", $newtid, $plays, $time));

        }

    }

}

In my function I use GROUP BY DATE( time ) ,so why the final query insert into the new table views_counts duplicates with the same time? 在我的函数中,我使用GROUP BY DATE( time ) ,那么为什么最终查询同时插入到新表中views_counts重复呢?

Here is my output : 这是我的输出

id  | tid | plays | time
----|-----|-------|--------------
1   | 1   | 2     | 2017-01-26 12:43:16
2   | 1   | 1     | 2017-01-27 12:45:24
3   | 1   | 2     | 2017-01-26 12:43:16
4   | 1   | 1     | 2017-01-27 12:45:24
5   | 3   | 30    | 2016-12-26 18:20:16
6   | 1   | 2     | 2017-01-26 12:43:16
7   | 1   | 1     | 2017-01-27 12:45:24
8   | 1   | 2     | 2017-01-26 12:43:16
9   | 1   | 1     | 2017-01-27 12:45:24
10  | 3   | 30    | 2016-12-26 18:20:16
11  | 1   | 2     | 2017-01-26 12:43:16
12  | 1   | 1     | 2017-01-27 12:45:24
13  | 1   | 2     | 2017-01-26 12:43:16
14  | 1   | 1     | 2017-01-27 12:45:24
15  | 3   | 30    | 2016-12-26 18:20:16

As you see I have multiple same results for the same time. 如您所见,我同时具有多个相同的结果。

Here is what I expected: 这是我所期望的:

id  | tid | plays | time
----|-----|-------|--------------
1   | 1   | 2     | 2017-01-26 12:43:16
2   | 1   | 1     | 2017-01-27 12:45:24
3   | 3   | 30    | 2016-12-26 18:20:16

UPDATE UPDATE

Here it is how I call this "one time" function: 这就是我所说的“一次”功能:

<?php
    include("/var/www/html/includes/config.php");
    include("/var/www/html/includes/classes.php");
    session_start();
    $db = new mysqli($CONF['host'], $CONF['user'], $CONF['pass'], $CONF['name']);
    if ($db->connect_errno) {
        echo "Failed to connect to MySQL: (" . $db->connect_errno . ") " . $db->connect_error;
    }
    $db->set_charset("utf8");

    $feed = new feed();
    $feed->db = $db;                
    $result = $feed->countViews();

    mysqli_close($db);
?>

The function countViews() is inside classes.php . 函数countViews()classes.php

I call this PHP just going to visit the requested page through the web. 我称此PHP仅用于通过Web访问请求的页面。

I would propose to solve your issue using just one query. 我建议仅使用一个查询来解决您的问题。

function countViews() {
    $query = $this->db->query("SELECT COUNT( * ) AS plays , `time`, `track` FROM `views` GROUP BY `track`,DATE( `time` );"); 
    while($row = $query->fetch_assoc()) {
        $this->db->query(sprintf("INSERT INTO views_counts (tid,plays,time) VALUES ('%s','%s','%s')", $row['track'], $row['plays'], $row['time']));
    }
}

Try this: 尝试这个:

function countViews() {

    $query = "SELECT  `track` FROM  `views` GROUP BY `track`";
    $result = $this->db->query($query);

    while($row = $result->fetch_assoc()) {
        $rows[] = $row;
    }

    $rowsnew = array();

    foreach($rows as $row) {
        $tid = $row['track'];

        $querysel = $this->db->query(sprintf("SELECT COUNT( * ) AS plays , `time`, `track` FROM `views` WHERE `track` = '%s' GROUP BY DATE( `time` )", $tid)); 

        while($rownew = $querysel->fetch_assoc()) {
            $rowsnew[] = $rownew;
        }

    }

    foreach($rowsnew as $rownew1) {

        $newtid = $rownew1['track'];
        $plays = $rownew1['plays'];
        $time = $rownew1['time'];

        $this->db->query(sprintf("INSERT INTO views_counts (tid,plays,time) VALUES ('%s','%s','%s')", $newtid, $plays, $time));

    }

}

Can't it be done really in a single query? 真的不能在单个查询中完成吗?

INSERT INTO views_counts (tid, time, plays)
    SELECT       track, DATE(`time`), COUNT(*)
        FROM `views`
        GROUP BY track, DATE(`time`)

Note that the rows to INSERT come from the SELECT . 注意, INSERT的行来自SELECT

I took the liberty of using DATE(time) , otherwise, which time is picked is arbitrary. 我随意使用DATE(time) ,否则,选择哪个 time是任意的。

Ok, so only a single SELECT query should suffice, which will be as follows: 好的,因此只有一个SELECT查询就足够了,如下所示:

$query = "SELECT `track`, `time`, COUNT(*) AS `plays` FROM `views` 
                 GROUP BY `track`, DATE(`time`) 
                 ORDER BY `track`, DATE(`time`);"

$result = $this->db->query($query);

while($row = $result->fetch_assoc()) {
    $newtid  =  $row['track'];
    $plays   =  $row['plays'];
    $time    =  $row['time'];

    $this->db->query(sprintf("INSERT INTO views_counts (tid,plays,time) 
                                     VALUES ('%s','%s','%s')", 
                                     $newtid, $plays, $time));

}


And that should ideally do the trick. 理想情况下,这应该可以解决问题。 A simple query demonstration using manually created sample data: 使用手动创建的示例数据的简单查询演示:

create table views (track int, `time` timestamp);
insert into views VALUES(1, '2017-01-26 12:43:16');
insert into views VALUES(1, '2017-01-27 12:45:24');
insert into views VALUES(1, '2017-01-27 12:50:30');

insert into views VALUES(2, '2017-01-25 01:00:00');
insert into views VALUES(2, '2017-01-25 02:00:00');
insert into views VALUES(2, '2017-01-26 11:30:00');
insert into views VALUES(2, '2017-01-26 11:45:00');
insert into views VALUES(2, '2017-01-26 13:45:00');
insert into views VALUES(2, '2017-01-26 15:45:00');
insert into views VALUES(2, '2017-01-27 08:00:00');

insert into views VALUES(3, '2017-01-27 09:00:00');


SELECT `track`, `time`, COUNT(*) AS plays FROM views 
GROUP BY `track`, DATE(`time`) ORDER BY `track`, DATE(`time`);

Output produced using this query, which is what is expected to land in views_counts : 使用此查询产生的输出,这将是在views_counts

track  |  time                |    plays   
----------------------------------------------
1      |  2017-01-26 12:43:16 |    1
1      |  2017-01-27 12:45:24 |    2
2      |  2017-01-25 01:00:00 |    2
2      |  2017-01-26 11:30:00 |    4
2      |  2017-01-27 08:00:00 |    1
3      |  2017-01-27 09:00:00 |    1

Demo link 演示链接

Hope that helps... 希望有帮助...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM