Hi Im making a website in php with a microsoft access database through odbc and i have come across a small problem let me show you my codes first.
<form method ="POST" action="maxtimestamplog.php">
Longitude <input type="text" name="longitude" /><br/>
Latitude
<input type ="text" name = "latitude"/>
<input name="ok" type="submit" value="Submit" />
</form>
<?
$dbc = odbc_connect("X1","",""); // Trying to establish connection
// with database
echo "<br>";
$datetime =date('Y-m-d H:i:s', strtotime('+8 hours'));
echo "The Current date/time is $datetime";
echo "<br><br><br>";
if (!$dbc)
{
exit("Connection failed:".$dbc);
}
$x_origin = $_POST['longitude'];
$y_origin = $_POST['latitude'];
$query = " SELECT m.vehicle_no,
l.longitude,
l.latitude,
l.timestamp
FROM
vehicle_log AS l,
GPS_modem AS m
WHERE
m.modem_ID = l.modem_ID
AND l.timestamp = (
SELECT MAX(timestamp) FROM vehicle_log WHERE modem_ID = l.modem_ID
) order by timestamp desc
"; // SQL Statement
$rs = odbc_exec($dbc,$query);
if (!$rs)
{
exit("Error in SQL. ".$rs);
}
$i=1;
while (odbc_fetch_row($rs))
{
$lng = odbc_result($rs, "longitude");
$lat = odbc_result ($rs, "latitude");
$ts = odbc_result ($rs, "timestamp");
$vno = odbc_result ($rs, "vehicle_no");
$yyyy= substr($ts, 0, 4);
$mm= substr($ts, 5, 2);
$dd= substr($ts, 8,2);
$hr= substr($ts, 11, 2);
$min= substr($ts, 14,2);
$sec= substr($ts,17, 2);
$cyyyy= substr($datetime, 0, 4);
$cmm= substr($datetime, 5, 2);
$cdd= substr($datetime, 8,2);
$chr= substr($datetime, 11, 2);
$cmin= substr($datetime, 14,2);
$csec= substr($datetime,17, 2);
$ctss = $csec
+ ($cmin * 60)
+ ($chr * 60 * 60)
+ ($cdd * 24 * 60 * 60)
+ ($cmm * 30 * 24 * 60 * 60)
+ ($cyyyy * 365 * 24 * 60 * 60);
$tss = $sec
+ (cmin * 60) + ($hr * 60 * 60)
+ ($dd * 24 * 60 * 60)
+ ($mm * 30 * 24 * 60 * 60)
+ ($yyyy * 365 * 24 * 60 * 60);
$tssd = $ctss - $tss;
$x = $lng;
$y = $lat;
$i = $i + 1;
$xd = ($x - $x_origin);
$yd = ($y - $y_origin);
$d = ($xd*$xd) + ($yd*$yd);
$td = sqrt($d);
echo "Car Number $vno is at a distance $td away at timestamp $ts";
echo "</br></br>";
}
odbc_close($dbc);
?>
</HTML>
what I want to be done now is to only display one output not all.
Firstly I want to select only the data where variable $tssd is less than or equal to 10800 then i want to display the smallest $td out of what i selected and it shoud display
echo "Car Number $vno is at a distance $td away at timestamp $ts";
echo "</br></br>";
where $td is the least within $tssd is less than 10800
It should only display one
please try to help me im quite new to php and my sql statement is quite messy as it is i make blunder out of it.
Try to separate the SQL from the PHP.
I believe you're asking how to return only a single row rather than all the rows. To accomplish this, use the "TOP" keyword. For example,
SELECT TOP 1
m.vehicle_no,
l.longitude,
l.latitude,
l.timestamp
For the second part of your question, "where $td is the least within $tssd is less than 10800", we do not know the column names that these relate to. If we pretend they're named TD and TSSD in the vehicle_log table, then your statement might look like this:
SELECT TOP 1 m.vehicle_no,
l.longitude,
l.latitude,
l.timestamp,
l.TD,
l.TSSD
FROM
vehicle_log AS l,
GPS_modem AS m
WHERE
m.modem_ID = l.modem_ID
AND l.timestamp = (
SELECT MAX(timestamp) FROM vehicle_log WHERE modem_ID = l.modem_ID
)
AND l.TD <= 10800
order by l.TD ASC
Lastly, I changed the ORDER BY to accommodate "i want to display the smallest $td".
If this is not what you are looking for, can you provide more information?
Related
I would like to calculate the total distance of driving beetween multiple locations (loop), including the distance (starting point (garage) - first location sarting point) and (last location finishig point - finishing point (garage)).
Example:
(Garage + D1) + (D1 + D2) + (D2 + E1) + (E1 + E2) + E2 + Garage)
I'm having a problem with the correct looping. Here's my simplified code:
<?
$driver = 5;
$result2 = mysql_query("SELECT * FROM test WHERE id='$driver' LIMIT 1") or die(mysql_error());
while($row2 = mysql_fetch_array( $result2 )) {
$lon=$row2['lon'];
$lat=$row2['lat'];
echo "$lon, $lat";
}
$result = mysql_query("SELECT * FROM test1 WHERE driver='$driver'") or die(mysql_error());
while($row = mysql_fetch_array( $result )) {
$lon1=$row['lon1'];
$lat1=$row['lat1'];
$lon2=$row['lon2'];
$lat2=$row['lat2'];
////////// distance between driver address and starting address
$distancecalc = (3958*3.1415926*sqrt(($lat-$lat1)*($lat-$lat1) + cos($lat/57.29578)*cos($lat1/57.29578)*($lon-$lon1)*($lon-$lon1))/180);
////////// distance between statring address and finishing address - multiple adsresses
$distancecalc1 = $distancecalc1 + (3958*3.1415926*sqrt(($lat2-$lat1)*($lat2-$lat1) + cos($lat2/57.29578)*cos($lat1/57.29578)*($lon2-$lon1)*($lon2-$lon1))/180);
////////// distance between finishing address and driver address
$distancecalc2 = (3958*3.1415926*sqrt(($lat2-$lat)*($lat2-$lat) + cos($lat2/57.29578)*cos($lat/57.29578)*($lon2-$lon)*($lon2-$lon))/180);
$distancetotal = $distancecalc + $distancecalc1 +$distancecalc2;
echo "$distancecalc<br>
$distancecalc1<br>
$distancecalc2<br>";
}
echo "$distancetotal";
?>
I tried some things (mostly if... ) and also with more database requests, but I'm still having the problem of avoiding multiple calculations, and I also strongly believe there is way to code it to make it easier and clearer.
I would appreciate some help on this one.
Thank you very much.
Here's the function you need:
function distance ($lat1, $lon1, $lat2, $lon2) {
return (3958*3.1415926*sqrt(($lat2-$lat1)*($lat2-$lat1) + cos($lat2/57.29578)*cos($lat1/57.29578)*($lon2-$lon1)*($lon2-$lon1))/180);
}
The function body is exactly the same as the formula you used in-line, so I don't understand why you needed help with this.
The number 6367 - is the radius of the Earth in kilometers
DELIMITER $$
DROP FUNCTION IF EXISTS geodist $$
CREATE FUNCTION geodist (
src_lat DECIMAL(9,6), src_lon DECIMAL(9,6),
dst_lat DECIMAL(9,6), dst_lon DECIMAL(9,6)
) RETURNS DECIMAL(6,2) DETERMINISTIC
BEGIN
SET #dist := 6367 * 2 * ASIN(SQRT(
POWER(SIN((src_lat - ABS(dst_lat)) * PI()/180 / 2), 2) +
COS(src_lat * PI()/180) *
COS(ABS(dst_lat) * PI()/180) *
POWER(SIN((src_lon - dst_lon) * PI()/180 / 2), 2)
));
RETURN #dist;
END $$
DELIMITER ;
Ok. I worked it out with help of mac_gyver (php freaks). All calculations are done as i wish. My code below:
<?
include "connectdb.php";
$driver = 5;
$datestamp = '2013/05/07';
$result2 = mysql_query("SELECT * FROM drivers WHERE id='$driver' LIMIT 1") or die(mysql_error());
while($row2 = mysql_fetch_array( $result2 )) {
$lon=$row2['lon'];
$lat=$row2['lat'];
}
$result = mysql_query("SELECT * FROM quotedb WHERE moveday='$datestamp' AND driver='$driver' AND cleared='Not Cleared' AND status='Done' ORDER BY moveday, timeday") or die(mysql_error());
$distance = 0; // accumulate the distance
$first_pass = true; // flag to detect the first row inside the loop
while($row = mysql_fetch_assoc( $result )) {
$lon2a=$lon2;
$lat2a=$lat2;
$lon1=$row['lon1'];
$lat1=$row['lat1'];
$lon2=$row['lon2'];
$lat2=$row['lat2'];
// calculate the distance from the Garage to the first point of the first row
if($first_pass){
$distance += (3958*3.1415926*sqrt(($lat-$lat1)*($lat-$lat1) + cos($lat/57.29578)*cos($lat1/57.29578)*($lon-$lon1)*($lon-$lon1))/180);
$first_pass = false;
}
// calculate the distance for each row (segment) in the route
$distance += (3958*3.1415926*sqrt(($lat2-$lat1)*($lat2-$lat1) + cos($lat2/57.29578)*cos($lat1/57.29578)*($lon2-$lon1)*($lon2-$lon1))/180);
if ( $lon2a == "" or $lat2a =="" ) {
} else {
// calculate the distance from the second point of the first row to the first point of the next row
$distance += (3958*3.1415926*sqrt(($lat2a-$lat1)*($lat2a-$lat1) + cos($lat2a/57.29578)*cos($lat1/57.29578)*($lon2a-$lon1)*($lon2a-$lon1))/180);
}
}
// calculate the distance from the second point of the last row to the Garage
$distance += (3958*3.1415926*sqrt(($lat2-$lat)*($lat2-$lat) + cos($lat2/57.29578)*cos($lat/57.29578)*($lon2-$lon)*($lon2-$lon))/180);
echo "$distance<br>
";
?>
Still think there is a place for improvement in the code. Will aplay Haversine method for calculations. Do you guys have some suggestion to improve this piece of code ... thx
Impoved version:
<?
include "connectdb.php";
$driver = 5;
$datestamp = '2013/05/07';
$result2 = mysql_query("SELECT * FROM drivers WHERE id='$driver' LIMIT 1") or die(mysql_error());
while($row2 = mysql_fetch_array( $result2 )) {
$garage_lon=$row2['lon'];
$garage_lat=$row2['lat'];
}
$result = mysql_query("SELECT * FROM quotedb WHERE moveday='$datestamp' AND driver='$driver' AND cleared='Not Cleared' AND status='Done' ORDER BY moveday, timeday") or die(mysql_error());
function calculate_distance($lon1, $lat1, $lon2, $lat2) {
return (3958 * 3.1415926 * sqrt(($lat2 - $lat1) * ($lat2 - $lat1) + cos($lat2 / 57.29578) * cos($lat1 / 57.29578) * ($lon2 - $lon1) * ($lon2 - $lon1)) / 180);}
$previous_lon = $garage_lon;
$previous_lat = $garage_lat;
$distance = 0; // accumulate the distance
while($row = mysql_fetch_assoc( $result ))
{
$lon1 = $row['lon1'];
$lat1 = $row['lat1'];
$lon2 = $row['lon2'];
$lat2 = $row['lat2'];
if ( $previous_lon && $previous_lat )
{
// calculate the distance from the second point of the first row to the first point of the next row
$distance += calculate_distance($lon1, $lat1, $previous_lon, $previous_lat);
}
// calculate the distance for each row (segment) in the route
$distance += calculate_distance($lon1, $lat1, $lon2, $lat2);
$previous_lon = $lon2;
$previous_lat = $lat2;
}
// calculate the distance from the second point of the last row to the Garage
$distance += calculate_distance($garage_lon, $garage_lat, $lon2, $lat2);
$distance = round($distance,0);
echo "$distance<br>
";
?>
Could anyone solve my problem please.
I have mysql table with time_start 'hour:minute' and time_end 'hour:minute' how can i get cumulative time duration between time_start and time_end.
thanks,
$sel = $db->query("SELECT * FROM logbook WHERE date = '$date' ");
while($sel_row = mysqli_fetch_array($sel))
{
$duration = (strtotime($sel_row['time_end'])-strtotime($sel_row['time_start']))/(60*60);
$hour = floor($duration);
$minute = ($duration - $hour)*60;
echo $hour.":".$minute;
? HERE HOW CAN I CUMULATE THE $hour:$minute
}
Do the summation where you calculate the duration
$duration = 0;
while($sel_row = mysqli_fetch_array($sel))
{
$duration += (strtotime($sel_row['time_end'])-strtotime($sel_row['time_start']))/(60*60);
}
$hour = floor($duration);
$minute = ($duration - $hour)*60;
echo $hour.":".$minute;
Or better, let MySQL do the calculation:
SELECT (SUM(time_end) - SUM(time_start)) / 3600 FROM logbook WHERE date = '$date';
I have two columns in a row: min_value, max_value. Is there a way to do a select like:
SELECT RAND(`min_v`, `max_v`) `foo` [..]
I do realize that RAND does a different thing; the closest I came up (with help) is (RAND() * (max-min))+min, though it will produce a float number, which I'd need then to ROUND() and this is just completely wrong.
Unless anyone can suggest an alternative (which would be very useful), I will go PHP way.
Actually, ROUND((RAND() * (max-min))+min) is the best way in MySQL to do what you'd like. It is also the best way in ActionScript, JavaScript, and Python. Honestly, I prefer it to the PHP way because it is more convenient.
Because I don't know how many rows you'll be returning, I can't advise you whether it is better to use PHP or MySQL for this, but if you're dealing with a large number of values you probably are better off using MySQL.
Addendum
So, there was a question as to whether this is better in PHP or MySQL. Instead of getting into a debate on principles, I ran the following:
<pre><?php
$c = mysql_connect('localhost', 'root', '');
if(!$c) die('!');
echo mysql_select_db('test', $c)?'Connection':'Failure';
echo PHP_EOL;
echo ':::::::::::::::::::::::::BEGINNING MYSQL RAND::::::::::::::::::::::::::::::'.PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
$r = mysql_query( 'SELECT ROUND(RAND() * (200-10) + 10) FROM dual' );
$r = mysql_fetch_array( $r );
}
$end = microtime(1);
echo ($end - $start) . " for MySQL select".PHP_EOL;
echo ':::::::::::::::::::::::::BEGINNING PHP RAND::::::::::::::::::::::::::::::' .PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
$r = mysql_query( 'SELECT 200 AS two, 10 AS tem FROM dual' );
$r = mysql_fetch_array( $r );
$r[2]= rand($r[0], $r[1]);
}
$end = microtime(1);
echo ($end - $start) . " for PHP select".PHP_EOL;
MySQL is faster by about 2-3%.
If you use this, however (note, more columns return by MySQL):
<pre><?php
$c = mysql_connect('localhost', 'root', '');
if(!$c) die('!');
echo mysql_select_db('test', $c)?'Connection':'Failure';
echo PHP_EOL;
echo ':::::::::::::::::::::::::BEGINNING MYSQL RAND::::::::::::::::::::::::::::::'.PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
$r = mysql_query( 'SELECT ROUND(RAND() * (200-10) + 10) as rd, 200 as two, 10 as ten FROM dual' );
$r = mysql_fetch_array( $r );
}
$end = microtime(1);
echo ($end - $start) . " for MySQL select".PHP_EOL;
echo ':::::::::::::::::::::::::BEGINNING PHP RAND::::::::::::::::::::::::::::::' .PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
$r = mysql_query( 'SELECT 200 AS two, 10 AS tem FROM dual' );
$r = mysql_fetch_array( $r );
$r[2]= rand($r[0], $r[1]);
}
$end = microtime(1);
echo ($end - $start) . " for PHP select".PHP_EOL;
MySQL comes out behind by 3-4% (very inconsistent results) (about the same results if you don't use an array index assignment for $r[2]).
The major difference, it seems, comes from the number of records return to PHP and not the randomization system itself. So, if you need column A, column B, and a random value, use PHP. If you only need the random value, then use MySQL.
This method guarantees the same statistical probability for each value:
SELECT FLOOR((RAND() * (max-min+1))+min)
in case minimum range is 1, you can simply
SELECT FLOOR((RAND() * max_range) + 1)
in case minimum range is 0, you can even more simply
SELECT FLOOR((RAND() * max_range))
Could you do something like this?
SELECT id, (FLOOR( 1 + RAND( ) *60 )) AS timer
FROM users
LIMIT 0 , 30
See this post
Depending on how many rows you have in the table(s), using rand() in a query or subquery can be extremely slow.
You can seriously improve the speed by first putting the random value in a variable and then just using that in your query.
For example on a table with over 4 million rows...
This took over 10 minutes:
SELECT
*
FROM
`customers` `Customer`
WHERE
`id` = (
SELECT
FLOOR((RAND() * (max(`CustomerRand`.`id`) - min(`CustomerRand`.`id`) + 1)) + min(`CustomerRand`.`id`)) `random_id`
FROM
`customers` `CustomerRand`
);
While this took about 3 seconds on average:
SELECT
FLOOR((RAND() * (max(`CustomerRand`.`id`) - min(`CustomerRand`.`id`) + 1)) + min(`CustomerRand`.`id`)) `random_id`
FROM `customers` `CustomerRand` INTO #rand_id;
SELECT * FROM `customers` WHERE `id` = #rand_id;
You might even be able to put this into a stored procedure then if it's something you would want to do or re-use often. The stored procedure could then be called from PHP or Python or wherever
You can use order by rand
SELECT virtual.num
FROM (
SELECT 1 AS num UNION
SELECT 2 AS num UNION
SELECT 3 AS num
) virtual
ORDER BY RAND()
LIMIT 1
ok i have a database that has 3 fields planetkey, xcoord, ycoord...
i want to find all the planetkeys within 30 of the location entered.. this is what i have...
$sql2 = "SELECT * FROM adlplanet WHERE SQRT(POW(xcoord - 172.3900, 2) + POW(ycoord - 247.5000, 2) < 30";
$queryrow2 = mysql_query($sql2);
while ($jumpl = mysql_fetch_array($queryrow2)) {
echo $jumpl['PlanetKey '];
}
The formula is (x-a)^2 + (y-b)^2 = c^2
So the 30 should be 30^2:
$sql2 = "SELECT * FROM adlplanet WHERE SQRT(POW(xcoord - 172.3900, 2) + POW(ycoord - 247.5000, 2) < POW(30,2)";
I was wondering what is the best way to write the where statement in PHP where targetDate < Date.Now - HardCodedHours in PHP
If you mean how to do it in an MySQL query:
SELECT * FROM table WHERE targetDate <= date_sub(now(), interval 1 hour);
This will pull "field1" from table "myTable" where a DATETIME column "targetDate" is older than 12 hours.
$hardcodedHours = 12;
$sql = "SELECT field1 FROM myTable WHERE targetDate <= '" . date('Y-m-d H:i:s', strtotime("-$hardcodedHours hours")) . "'";
$result = mysql_query($sql);
$limitTime = time() - $nbHours * 3600;
$query = "SELECT ... WHERE TIMESTAMP(targetDate) < $limitTime;";
Or something like that.