IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Extraire une seule ligne avec des JOIN


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 195
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 195
    Par défaut Extraire une seule ligne avec des JOIN
    Bonjour,

    J'ai des stations qui enregistrent des mesures. Chaque station a 3 capteur.
    Quand une station prend un mesure c'est une collection (une collection de mesures)

    Il y a 4 stations.

    J'ai besoin de connaitre la date et l'ID de la dernière collection de chaque station.

    Pour cela, j'ai fait ceci qui fonctionne

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $sql_measures ='SELECT st.id_station, m.value, c.ttn_m_time, c.id_collection FROM stations AS st
    			INNER JOIN sensors AS se ON st.id_station = se.stations_id_station
    			INNER JOIN sensor_types AS stype ON se.sensor_types_id_sensor_type = stype.id_sensor_type
    			INNER JOIN measures AS m ON se.id_sensor = m.sensors_id_sensor
    			INNER JOIN collections AS c ON m.collections_id_collection = c.id_collection
    			WHERE st.id_station = '.$collection['id_station'].'
    			ORDER BY c.ttn_m_time DESC';
     
    			$r_measures = $connect->query($sql_measures) or die($connect->error);
     
     
    			while($result_measures = $r_measures->fetch_assoc())
    			{
    					echo '<pre>';
    					print_r($result_measures);
    					echo '</pre>';
    			}
    Mais le problème, il m'affiche toutes les mesures de chaque station en affichant en premier, les mesures de la collection la plus récente.

    Ce que j'ai besoin c'est qu'il m'affiche la une ligne, soit la première.

    J'ai donc essayé ceci (j'ai supprimé m.value, car je n'ai pas besoins des valeurs de toutes les collections, mais juste la date et l'ID de la dernière collection pour chaque station

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $sql_measures ='SELECT st.id_station, c.ttn_m_time, c.id_collection FROM stations AS st
    			INNER JOIN sensors AS se ON st.id_station = se.stations_id_station
    			INNER JOIN sensor_types AS stype ON se.sensor_types_id_sensor_type = stype.id_sensor_type
    			INNER JOIN measures AS m ON se.id_sensor = m.sensors_id_sensor
    			INNER JOIN collections AS c ON m.collections_id_collection = c.id_collection
    			WHERE st.id_station = '.$collection['id_station'].'
    			ORDER BY c.ttn_m_time DESC LIMIT 1';
     
    			$r_measures = $connect->query($sql_measures) or die($connect->error);
     
     
    			while($result_measures = $r_measures->fetch_assoc())
    			{
    					echo '<pre>';
    					print_r($result_measures);
    					echo '</pre>';
    			}
    Le oriblème ci-dessus, c'est que ke fait que j'ajoite LIMIT 1, il m'affiche une message d'erreur
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ORDER BY c.ttn_m_time DESC' at line 6
    je pense que c'est du fait qu'un LIMIT ne peut pas fonctionner avec des JOIN tel que présenté, mais j'ai besoin de connaitre la dernière collection enregistrée.

    Comment puis-je appliqué un LIMIT 1, sur une la table collections?
    Comment modifiriez-vous ma requête, de manière à ce qu'il parcours les mesures de la dernière collection sauvée pour une station

    J'espère avoir fourni assez d'information
    Mercii

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 987
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 987
    Par défaut
    Si j'ai bien compris, je dirais:
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT st.id_station,
           max(c.ttn_m_time),
           c.id_collection
    FROM stations AS st
    INNER JOIN sensors AS se
      ON st.id_station = se.stations_id_station
    INNER JOIN measures AS m
      ON se.id_sensor = m.sensors_id_sensor
    INNER JOIN collections AS c
      ON m.collections_id_collection = c.id_collection
    GROUP BY st.id_station

    qui donne la dernière date (la plus grande) pour toutes les stations. J'ai donc supprimé la clause WHERE ainsi que la jointure avec sensor_types qui ne servent pas, et j'ai utilisé la fonction d'agrégation max() qui mécaniquement réduira le nombre de résultat à 1 pour chaque station.

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 195
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 195
    Par défaut
    Hello Merci
    Ca marche pas tout à fait.
    En fait il faut que ca soit la date la plus grande pour toutes les collection

    Dans ce cas
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    $sql_measures ='SELECT st.id_station, c.id_collection, max(c.ttn_m_time) FROM stations AS st
    			INNER JOIN sensors AS se ON st.id_station = se.stations_id_station
    			INNER JOIN measures AS m ON se.id_sensor = m.sensors_id_sensor
    			INNER JOIN collections AS c ON m.collections_id_collection = c.id_collection
    			ORDER BY id.station DESC';
     
    			$r_measures = $connect->query($sql_measures) or die($connect->error);
     
     
    			while($result_measures = $r_measures->fetch_assoc())
    			{
    					echo '<pre>';
    					print_r($result_measures);
    					echo '</pre><hr>';
    			}
    Il me retourne bien qu'une ligne, mais l'ID de ka collection est 50, alors que je suis a la collection 7451
    Par contre il ne me retourne que pour une station

    Je me demande su je devrais faire ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $sql_select_map = 'SELECT fi.threshold,fi.id_field, st.id_station, st.station_longname,st.station_lat,st.station_lng,st.station_alt,st.installed  FROM fields AS fi 
    	INNER JOIN stations AS st ON fi.id_field = st.fields_id_field
    	WHERE st.station_active = 1 AND st.map = 1
    	ORDER BY st.installed ASC';
    	$result_map = $connect->query($sql_select_map);
     
    	// https://gist.github.com/wboykinm/5730504
    	$geojson = array(
       		'properties'  => array()
    	);
     
     
     
     
    	foreach($result_map as $i => $collection)
    	{
    		echo '======================<pre>';
    	print_r($collection['id_station']);
     
    	echo '</pre>';
    }
    et j'ajoute ta proposition dans le dernier foreach avec le where
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE st.id_station = '.$collection['id_station'].'
    Je vais aussi essayer de faire a SELECT sur la collections avec le max et faire les JOIN au sens inverse..... Je ne sais pas si c'est possible mais je vais essayer maintenant

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 987
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 987
    Par défaut
    Désolé, j'ai édité mon post entre-temps, il ne finit pas par ORDER BY mais par GROUP BY. Peux-tu zipper un dump de ta base de données en pièce jointe STP.

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 195
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 195
    Par défaut
    Ha mince, j'avais pas vu ton dernier message

    Entre temps j0ai fait ceci qui marche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    	/*
    	* Search for station ID
    	*/	
    	$sql_select_station = 'SELECT fi.threshold,fi.id_field, st.id_station, st.station_longname,st.station_lat,st.station_lng,st.station_alt,st.installed  FROM fields AS fi 
    	INNER JOIN stations AS st ON fi.id_field = st.fields_id_field
    	WHERE st.station_active = 1 AND st.map = 1
    	ORDER BY st.installed ASC';
    	$result_station = $connect->query($sql_select_station);
     
    	// https://gist.github.com/wboykinm/5730504
    	$geojson = array(
       		'properties'  => array()
    	);
     
     
    	echo "<ul>";
    	foreach($result_station as $i => $stations)
    	{
    		echo '<li>';
    		echo "id_station: ".$stations['id_station'];
    		/*
    		* Search for lastest id_collection for each station as a collection for a station do not have the same date/time for each station
    		*/
    		$sql_select_collection = 'SELECT st.id_station,c.id_collection, c.ttn_m_time  FROM collections AS c
    			INNER JOIN measures AS m ON c.id_collection = m.collections_id_collection
    			INNER JOIN sensors AS se ON m.sensors_id_sensor = se.id_sensor
    			INNER JOIN stations AS st ON se.stations_id_station = st.id_station
    			WHERE st.id_station = '.$stations['id_station'].'
    			ORDER BY c.id_collection DESC LIMIT 1';
     
     
     
    			$result_collection = $connect->query($sql_select_collection) or die($connect->error);
     
    			echo "<ul>";
    			while($collections = $result_collection->fetch_assoc())
    			{
    					echo '<li><pre>';
    					print_r($collections);
    					echo '</pre></li>';
     
    					/*
    					* Seach each each measures for a collection
    					*/
    			}
    			echo "</ul></li>";
     
     
    	};
     
    	echo "</ul>";
    Mais ce qui m'embete, c'est que je fait 3 requetes (j'ai pas encore fait la troisième)
    La derniere serait sur la table collection qui va extraire les mesures, mais j'aurais aussi besoin de faire un JOIN sur les types de sensors
    Je trouve tout cela un peu complexe mais je vais revoir ta proposition avec le groupe

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 195
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 195
    Par défaut
    Voilà, ça ça marche, mais je trouve pas très gallant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    	/*
    	* Search for station ID
    	*/	
    	$sql_select_station = 'SELECT fi.threshold,fi.id_field, st.id_station, st.station_longname,st.station_lat,st.station_lng,st.station_alt,st.installed  FROM fields AS fi 
    	INNER JOIN stations AS st ON fi.id_field = st.fields_id_field
    	WHERE st.station_active = 1 AND st.map = 1
    	ORDER BY st.installed ASC';
    	$result_station = $connect->query($sql_select_station);
     
    	// https://gist.github.com/wboykinm/5730504
    	$geojson = array(
       		'properties'  => array()
    	);
     
     
    	echo "<ul>";
    	foreach($result_station as $i => $stations)
    	{
    		echo '<li>';
    		echo "id_station: ".$stations['id_station'];
    		/*
    		* Search for lastest id_collection for each station as a collection for a station do not have the same date/time for each station
    		*/
    		$sql_select_collection = 'SELECT st.id_station,c.id_collection, c.ttn_m_time  FROM collections AS c
    			INNER JOIN measures AS m ON c.id_collection = m.collections_id_collection
    			INNER JOIN sensors AS se ON m.sensors_id_sensor = se.id_sensor
    			INNER JOIN stations AS st ON se.stations_id_station = st.id_station
    			WHERE st.id_station = '.$stations['id_station'].'
    			ORDER BY c.id_collection DESC LIMIT 1';
     
     
     
    			$result_collection = $connect->query($sql_select_collection) or die($connect->error);
     
    			echo "<ul>";
    			while($collections = $result_collection->fetch_assoc())
    			{
    					echo '<li>';
    					echo "id_collection: ".$collections['id_collection'];
    					echo '</li>';
    					echo '<li>';
    					echo "id_collection: ".$collections['ttn_m_time'];
    					echo '</li>';
    					echo '<li>';
    					echo "Value: ";
     
    					echo "<ul>";
     
    					/*
    					* Seach each each measures for a collection
    					*/
    					$sql_select_measure = 'SELECT st.id_station,c.id_collection, c.ttn_m_time, m.value,stype.sensor_type_name  FROM collections AS c
    						INNER JOIN measures AS m ON c.id_collection = m.collections_id_collection
    						INNER JOIN sensors AS se ON m.sensors_id_sensor = se.id_sensor
    						INNER JOIN sensor_types AS stype ON se.sensor_types_id_sensor_type = stype.id_sensor_type
    						INNER JOIN stations AS st ON se.stations_id_station = st.id_station
    						WHERE c.id_collection = '.$collections['id_collection'].'
    						ORDER BY c.id_collection DESC';
     
    					$result_measure = $connect->query($sql_select_measure) or die($connect->error);
     
    					while($measures = $result_measure->fetch_assoc())
    					{
    						echo '<li>';
    						print_r($measures);
    						echo '</li>';
    					}
    					echo "</ul></li>";
     
    			}
    			echo "</ul></li>";
     
     
    	};
     
    	echo "</ul>";
    J'aurais préféré faire qu'une requête

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/04/2012, 11h57
  2. [PHP 5.0] Extraire une seule donnée avec SimpleXML
    Par kryogen dans le forum Langage
    Réponses: 2
    Dernier message: 14/12/2009, 12h09
  3. Faire une seule ligne avec deux echo
    Par d10g3n dans le forum Shell et commandes GNU
    Réponses: 8
    Dernier message: 23/06/2008, 20h11
  4. Réponses: 3
    Dernier message: 06/11/2007, 11h16
  5. Plusieures infos sur une seule ligne avec ou sans tableau
    Par Him dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 17/03/2006, 14h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo