[RESOLU] Calcul à la volée d'une liste MySQL par mémoire tampon

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [RESOLU] Calcul à la volée d'une liste MySQL par mémoire tampon

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par josse34 » 26 oct. 2013, 12:37

Bonjour.
Pour les prochains, il suffisait de faire cette fonction exemple qui trie en ordre décroissant (il suffit de changer par >) :

<?php
$tab = array(array(5,6,2),array(3,7,1),array(1,5,9),array(3,8,8),array(1,2,3),array(7,4,4),array(4,2,10));

usort($tab, "cmp2");

$tab = array_slice($tab, 0, 3);

print_r($tab);

function cmp2($a,$b) {
if ($a[2] == $b[2])
return 0;
return ($a[2] < $b[2]) ? -1 : 1;
}
?>

Merci!
Bye

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par josse34 » 25 oct. 2013, 17:50

Rien à faire, je n'arrive pas à trier les résultats correctement, j'ai toujours un souci!

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par josse34 » 25 oct. 2013, 14:32

J'ai un souci pour faire ressortir les 3 plus petites valeurs, j'ai déjà fait cela :
$nblignestableau = count ( $tableau );
$u = 0;
$v = 10000;
$w = 10000;

while($u < $nblignestableau){
     if($tableau[$u][2] < $v){
        $k = $w;
        $w = $v;
        $v = $tableau[$u][2];
        $x1 = $tableau[$u][0];
        $y1 = $tableau[$u][1];
        $z1 = $tableau[$u][2];                
     }elseif($tableau[$u][2] < $w){
        $k = $w;     
        $w = $tableau[$u][2];
        $x2 = $tableau[$u][0];
        $y2 = $tableau[$u][1];
        $z2 = $tableau[$u][2];     
     }elseif($tableau[$u][2] < $k){
        $k = $tableau[$u][2];      
        $x3 = $tableau[$u][0];
        $y3 = $tableau[$u][1];
        $z3 = $tableau[$u][2];     
    };
    $u = $u + 1;
  };
echo "$x1 - $y1 - $z1 <br><br>";
echo "$x2 - $y2 - $z2 <br><br>";
echo "$x3 - $y3 - $z3 <br><br>";
Au lieu de me sortir MONTPELLIER puis MARSILLARGUES (11.5652Km) puis VILLEUNEUVE LES MAGUELONE, il me fait :
34154001 - MONTPELLIER - 8.7669
30132004 - LA GRAND COMBE - 76.2123
34337001 - VILLENEUVE-LES-MAG - 16.5258
Merci!!

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par Mazarini » 25 oct. 2013, 13:58

(1000*1000)/2 doit être le nombre de distance à calculer

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par josse34 » 25 oct. 2013, 13:34

Si tu as 1000 lieux, tu peux pré-calculer les 500000 distances une fois pour toutes et exploiter ca ensuite. Ca me semble le plus simple.

Le fait que les coordonnées soit dans une seule zone complique les calculs inutilement, je trouve ca dommage. Dans le cas contraire, il y a toutes les fonctions pour faire les calculs avec mysql.
Salut!
Je ne comprend pas ton post, j'ai bien 1000 lieux mais pourquoi 500 000 distances?

Dans mon dernier post, le code fourni calcule deja bien toutes les distances et les insère dans un array :
Array (
[0] => Array ( [0] => 01033002 [1] => BELLEGARDE [2] => 312.7362 )
[1] => Array ( [0] => 01089001 [1] => AMBERIEU [2] => 286.4661 )
[2] => Array ( [0] => 01185004 [1] => HAUTEVILLE [2] => 294.8129 )
)

Reste pour moi (éventuellement à optimiser ce code) surtout à extraire les 3 plus petites distances du array!

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par Mazarini » 25 oct. 2013, 13:29

Si tu as 1000 lieux, tu peux pré-calculer les 500000 distances une fois pour toutes et exploiter ca ensuite. Ca me semble le plus simple.

Le fait que les coordonnées soit dans une seule zone complique les calculs inutilement, je trouve ca dommage. Dans le cas contraire, il y a toutes les fonctions pour faire les calculs avec mysql.

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par josse34 » 25 oct. 2013, 13:02

Slu!

Ben en fait, un éclair à traversé mon esprit et j'ai pondu ceci :
    $alt0_1 = 1;
    $alt0_2 = 1;
    $r0 = 6366;
    $gps_plant = "43.558379,4.068991";
    $gps_plant2 = explode(",", $gps_plant);
    $lat0_1 = $gps_plant2[0];
    $lon0_1 = $gps_plant2[1];

$connexion = new PDO('mysql:host=localhost;dbname=xmlmeteo', 'xmlmeteo', 'PASSWORD');
$connexion->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$connexion->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
$connexion->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$connexion->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);
$resultat=$connexion->query('SELECT description, name, coordinates FROM `xmlmeteo`');

while( $distance_gps = $resultat->fetch() )
  {
    $gps_plant = explode(",", $distance_gps->coordinates);
    $lat2 = $gps_plant[1];
    $lon2 = $gps_plant[0];
    
    $alt1 = $alt0_1;
    $alt2 = $alt0_2;
    $r = $r0;
    $lat1 = $lat0_1;
    $lon1 = $lon0_1;
    
    $lat1 = deg2rad($lat1);
		$lat2 = deg2rad($lat2);
		$lon1 = deg2rad($lon1);
		$lon2 = deg2rad($lon2);
 
		//recuperation altitude en km
		$alt1 = $alt1/1000;
		$alt2 = $alt2/1000;
 
		//calcul précis
		$dp= 2 * asin(sqrt(pow (sin(($lat1-$lat2)/2) , 2) + cos($lat1)*cos($lat2)* pow( sin(($lon1-$lon2)/2) , 2)));
 
		//sortie en km
		$d = $dp * $r;
 
		//Pythagore a dit que :
		 $h = round(sqrt(pow($d,2)+pow($alt2-$alt1,2)),4);
 
		$tableau[] = array($distance_gps->description, $distance_gps->name, $h);
  }

print_r($tableau);
ce qui me liste bien :
Array (
[0] => Array ( [0] => 01033002 [1] => BELLEGARDE [2] => 312.7362 )
[1] => Array ( [0] => 01089001 [1] => AMBERIEU [2] => 286.4661 )
[2] => Array ( [0] => 01185004 [1] => HAUTEVILLE [2] => 294.8129 )
)
Reste à en ressortir de $tableau[] les 3 plus petites valeurs!! Un MIN pourrait faire l'affaire mais ne concerne que l'unique valeur la plus petite?!

Merci!

Re: Calcul à la volée d'une liste MySQL par mémoire tampon

par moogli » 25 oct. 2013, 12:35

Salut,

Implémenter la chose en SQL + order by la distance (asc / desc suivant le cas) + limite.

Le mieux serait de créer une fonction ou procédure SQL.
Par contre je ne crois que mysql puisse retourner des tuples :/
Mais tu as moyen de faire quelque chose quand même ;)


@+

Calcul à la volée d'une liste MySQL par mémoire tampon

par josse34 » 25 oct. 2013, 12:07

Bonjour!

J'ai une base structurée comme suit avec des coordonnées GPS sur moins de 1000 lignes :
description | name | coordinates
01033002 | BELLEGARDE | 5.814167,46.0865
01089001 | AMBERIEU | 5.329333,45.9765
01185004 | HAUTEVILLE | 5.598167,45.979667

Je part d'une coordonnée GPS de type $gps_plant = "43.558379,4.068991";

Avec un explode on parviens à séparer latitude et longitude pour chacun et la fonction suivante permet de calculer la distance entre deux point GPS :
function distance($lat1, $lon1, $lat2, $lon2, $alt1, $alt2) 
	{
		//rayon de la terre
		$r = 6366;
		$lat1 = deg2rad($lat1);
		$lat2 = deg2rad($lat2);
		$lon1 = deg2rad($lon1);
		$lon2 = deg2rad($lon2);
 
		//recuperation altitude en km
		$alt1 = $alt1/1000;
		$alt2 = $alt2/1000;
 
		//calcul précis
		$dp= 2 * asin(sqrt(pow (sin(($lat1-$lat2)/2) , 2) + cos($lat1)*cos($lat2)* pow( sin(($lon1-$lon2)/2) , 2)));
 
		//sortie en km
		$d = $dp * $r;
 
		//Pythagore a dit que :
		 $h = round(sqrt(pow($d,2)+pow($alt2-$alt1,2)),4);
 
		return $h;
	}
Est il possible de calculer à la volée (en mémoire tampon donc) la distance entre $gps_plant et l'intégralité de la liste MySQL et en resortir les 3 lignes les moins distantes?

C'est à dire une probable mise en mémoire des 1000 distances calculées avant extraction des plus petites, car me concernant, je ne sais pas trop comment m'y prendre sans lourdeurs de type création d'une table SQL à chaque fois avec des centaines de lignes en description | distance + select en order by.

Merci!