J'ai un site Web de musique où chaque fois qu'un utilisateur clique sur jouer, ma fonction PHP s'insère dans le tableau views

J'essaie de réorganiser ma base de données MySQL pour l'optimiser en performances, j'ai donc essayé dans cet exemple de compter le total des vues pour chaque track groupé par temps.

Sélectionnez uniquement les pistes du tableau views:

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

Le résultat pour $query:

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

Comptez le nombre de lignes pour chaque résultat en lecture et groupez par date:

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

Le résultat pour $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   |

Insertion finale dans un nouveau tableau du résultat:

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

Voici ma fonction complète:

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));

        }

    }

}

Dans ma fonction, j'utilise GROUP BY DATE( heure ), alors pourquoi la requête finale insérée dans la nouvelle table views_counts se duplique avec la même heure?

Voici ma sortie :

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

Comme vous le voyez, j'ai plusieurs résultats identiques pour le même temps.

Voici ce que j'attendais:

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

MISE À JOUR

Voici comment j'appelle cette fonction "une fois":

<?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);
?>

La fonction countViews() est à l'intérieur de classes.php.

J'appelle cela PHP en allant simplement visiter la page demandée via le Web.

0
NineCattoRules 27 janv. 2017 à 13:36

4 réponses

Meilleure réponse

Je proposerais de résoudre votre problème en utilisant une seule requête.

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']));
    }
}
1
Peter Darmis 2 févr. 2017 à 18:46

Essaye ça:

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));

    }

}
0
NineCattoRules 2 févr. 2017 à 09:29

Cela ne peut-il pas être fait vraiment en une seule requête?

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

Notez que les lignes vers INSERT proviennent de SELECT.

J'ai pris la liberté d'utiliser DATE(time), sinon qui time est choisi est arbitraire.

0
Rick James 3 févr. 2017 à 01:47

Ok, donc une seule requête SELECT devrait suffire, qui sera comme suit:

$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));

}


Et cela devrait idéalement faire l'affaire. Une démonstration de requête simple à l'aide d'exemples de données créés manuellement:

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`);

Sortie produite à l'aide de cette requête, qui est censée aboutir dans 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

Lien de démonstration

J'espère que cela pourra aider...

-1
Dhruv Saxena 2 févr. 2017 à 01:28