Check if two ranges intersect in a database with php - php

I have a database that has 2 columns Left_From and Left_To I need to basically check both columns with each row in the database to see if there is any overlapping ranges. So lets say there are 37 rows returned I need to check each row 37 times. I have tried array_intersect() with ranges and multiple loops. I have also tried BETWEEN in mysql but that does do what I need it to either. When I tried the between method I have two loops that I thought would take these two
$newstart[$crow] = $row['LEFT_FROM'];
$newend[$crow] = $row['LEFT_TO'];
and compare them to the new data that would be looped through 37 times because of $row2.
//attempt at BETWEEN
$newstart = array();
$newend = array();
$crow = 0;
while ($row = mysqli_fetch_array($get)) {
$newstart[$crow] = $row['LEFT_FROM'];
$newend[$crow] = $row['LEFT_TO'];
while ($row2 = mysqli_fetch_array($get)) {
$newsql = "SELECT * FROM database+table WHERE tablename = 'something' AND
LEFT_FROM BETWEEN " . $newstart[$crow] . " AND " . $newend[$crow] . " OR
LEFT_TO BETWEEN " . $newstart[$crow] . " AND " . $newend[$crow] . " OR ".
$newstart[$crow] . " BETWEEN " . "LEFT_FROM" . " AND ". " LEFT_TO";
$result = mysqli_query($GLOBALS['Con'], $newsql);
if (!$result) {
echo "Error: " . mysqli_error($GLOBALS['Con']) . "<br>";
}
if (!empty($result)) {
echo "Overlap: ". "Row2 LEFT_FROM: " . $row2['LEFT_FROM'] . " NewStart: " . $newstart[$crow] . " Row2 LEFT_TO: " . $row2['LEFT_TO'] . " Newend: " . $newend[$crow] . "<br>" . "Crow: " . $crow . "<br>" ;
}
}
echo "Crow: " . $crow . "<br>";
$crow++;
}
atempt at array_intersect all variables in arrays are set to 0
$result = mysqli_query($GLOBALS['con'], $select);
$Rows = $result->num_rows;
$Rows2 = $Rows;
$Rows3 = $Rows;
$Rows4 = $Rows;
$Rows5 = $Rows;
$range1 = array();
$range2 = array();
$range3 = array();
$range4 = array();
while ($counter <= $Rows) {
$range1[$crow] = $leftfrom[$add];
$range2[$crow] = $leftto[$add];
$counter++;
$road++;
$crow++;
}
while ($counter2 <= $Rows2) {
$range3[$crow2] = $leftfrom[$add2];
$range4[$crow2] = $leftto[$add2];
$counter2++;
$road3++;
$crow2++;
}
$Combined1 = array();
$Combined1 = array();
while ($counter3 <= $Rows3) {
$Combined1[$crow5] = range($range1[$crow3], $range2[$crow3]);
$Combined2[$crow6] = range($range3[$crow3], $range4[$crow3]);
$crow5++;
$crow6++;
$crow3++;
$counter3++;
}
$check1 = 0;
while ($check1 <= $Rows4) {
$GLOBALS['check2'] = 0;
$Rows6 = $GLOBALS['check2'] + 1;
while ($GLOBALS['check2'] <= $Rows5) {
$results = array_intersect($Combined1[$check1],$Combined2[$Rows6]);
if ($results) {
$start = reset($results);
$end = end($results);
echo "These are overlapping" . "<br>";
echo "Start of overlap: " . $start . " Rows#: " . $check1 . " Bad Row: " . $GLOBALS['check2'];
echo "<br>";
echo "end of overlap: " . $end;
echo "<br>" . $GLOBALS['check2'] ;
$GLOBALS['check2']++;
}else{
echo "<br>" . $check1 . " No duplicates" . "<br>";
$GLOBALS['check2']++;
}
}
$check1++;
}

You don't need a loop in PHP, you can do it entirely by joining the table with itself.
SELECT *
FROM yourTable AS t1
JOIN yourTable AS t2
ON t1.id < t2.id
AND (t1.left_from <= t2.left_to AND t2.left_from <= t1.left_to)
t1.id < t2.id keeps it from treating a row as overlapping with itself (and using < rather than != keeps it from showing the same pair of rows twice). Replace id with the primary key of your table.

To check, if two number ranges overlap, you could use the simple test x1 < y2 AND y1 < x2. This could be combined in a single sql statement.
SELECT
t1.LEFT_FROM as LEFT_FROM_1,
t1.LEFT_TO as LEFT_TO_1,
t2.LEFT_FROM as LEFT_FROM_2,
t2.LEFT_TO as LEFT_TO_2
FROM
t t1, t t2
WHERE
t1.LEFT_FROM < t2.LEFT_TO AND t2.LEFT_FROM < t1.LEFT_TO
This query would return all overlapping ranges.

Related

Getting JSON error after filtering data but Page loads fine without filtering

I have a grid that loads fine until I try to apply a filter then i get the following error.
Fatal error: Uncaught Error: Call to a member function fetch_assoc() on bool in
// build the query.
$result = $conn->query($query) or die("SQL Error 1: " . mysqli_error());
$sql = "SELECT FOUND_ROWS() AS `found_rows`;";
$rows = $conn->query($sql);
$rows = mysqli_fetch_assoc($rows);
$total_rows = $rows['found_rows'];
$query = "SELECT SQL_CALC_FOUND_ROWS profile_pic_url, username, full_name, biography, edge_followed_by, edge_follow FROM owner ORDER BY edge_followed_by DESC LIMIT $start, $total_rows".$where." ";
}
}
$result = $conn->query($query) ;
$sql = "SELECT FOUND_ROWS() AS `found_rows`;";
$rows = $conn->query($sql);
$rows = mysqli_fetch_assoc($rows);
$total_rows = $rows['found_rows'];
$orders = null;
// get data and store in a json array
while($row = $result->fetch_assoc()) {
#kryptur - this is where $where is defined
// filter data.
if (isset($_GET['filterscount']))
{
$filterscount = $_GET['filterscount'];
if ($filterscount > 0)
{
$where = " WHERE (";
$tmpdatafield = "";
$tmpfilteroperator = "";
for ($i=0; $i < $filterscount; $i++)
{
// get the filter's value.
$filtervalue = $_GET["filtervalue" . $i];
// get the filter's condition.
$filtercondition = $_GET["filtercondition" . $i];
// get the filter's column.
$filterdatafield = $_GET["filterdatafield" . $i];
// get the filter's operator.
$filteroperator = $_GET["filteroperator" . $i];
if ($tmpdatafield == "")
{
$tmpdatafield = $filterdatafield;
}
else if ($tmpdatafield <> $filterdatafield)
{
$where .= ")AND(";
}
else if ($tmpdatafield == $filterdatafield)
{
if ($tmpfilteroperator == 0)
{
$where .= " AND ";
}
else $where .= " OR ";
}
// build the "WHERE" clause depending on the filter's condition, value and datafield.
switch($filtercondition)
{
case "CONTAINS":
$where .= " " . $filterdatafield . " LIKE '%" . $filtervalue ."%'";
break;
case "DOES_NOT_CONTAIN":
$where .= " " . $filterdatafield . " NOT LIKE '%" . $filtervalue ."%'";
break;
case "GREATER_THAN":
$where .= " " . $filterdatafield . " > '" . $filtervalue ."'";
break;
case "LESS_THAN":
$where .= " " . $filterdatafield . " < '" . $filtervalue ."'";
break;
case "GREATER_THAN_OR_EQUAL":
$where .= " " . $filterdatafield . " >= '" . $filtervalue ."'";
break;
case "LESS_THAN_OR_EQUAL":
$where .= " " . $filterdatafield . " <= '" . $filtervalue ."'";
break;
}
if ($i == $filterscount - 1)
{
$where .= ")";
}
$tmpfilteroperator = $filteroperator;
$tmpdatafield = $filterdatafield;
}

Converting .Net API to PHP

I have this .Net REST API function modified from the demo for a grid control here: http://gijgo.com/grid/demos/ajax-sourced-data.
However, I am using PHP on the backend.
public JsonResult Get(int? page, int? limit)
{
List<Models.inventory> records;
int total;
using (ApplicationDbContext context = new ApplicationDbContext())
{
var query = context.inventory.Select(p => new Models.inventory
{
id = p.id,
company = p.company,
part = p.part,
year = p.year,
model = p.model,
stock = p.stock,
ic = p.ic,
vin = p.vin,
status = p.status,
bodycolor = p.bodycolor,
condition = p.condition,
comments = p.comments,
miles = p.miles,
price = p.price,
qty = p.qty
});
query = query.OrderBy(q => q.id);
total = query.Count();
if (page.HasValue && limit.HasValue)
{
int start = (page.Value - 1) * limit.Value;
records = query.Skip(start).Take(limit.Value).ToList();
}
else
{
records = query.ToList();
}
}
return this.Json(new { records, total }, JsonRequestBehavior.AllowGet);
}
I have converted the function to PHP but am having difficulty with the pagination because the total records isn't really being sent.
The C# code, filters the data after the query and i'm not sure how to do that with PHP and PostgreSQL.
I also want to return the total number of rows without the limit and offset in the result I suppose I'm going to have to run a 2nd query to return that data,
is that correct or can I do it in another way?
private function GetInventory()
{
$ic=$_request['ic'];
$limit=$_request['limit'];
$offset=$_request['page']-1;
$sql = "SELECT u.id, "
. " (SELECT company FROM urgss.users WHERE id = u.id) AS company, "
. " u.itemname || ' (' || u.part || ')' as part, "
. " u.year, "
. " u.model, "
. " u.stockno AS stock, "
. " u.ic AS ic, "
. " u.vin, "
. " u.status || ' / ' || u.currentstatus AS status, "
. " REGEXP_REPLACE(u.bod_col, '[\[\]]', '', 'g') AS bodycolor, "
. " u.condition, "
. " u.comments, "
. " CASE "
. " WHEN u.miles::integer < 1000 THEN "
. " u.miles::INTEGER * 1000 "
. " ELSE "
. " u.miles::INTEGER "
. " END AS miles, "
. " CASE "
. " WHEN u.rprice > 0 THEN "
. " u.rprice "
. " ELSE "
. " NULL "
. " END AS price, "
. " u.qty "
. "FROM unet u "
. "WHERE ic = '" . $ic. "' "
. "AND year::integer > 0"
. " LIMIT " . $limit . " OFFSET ". ($offset * $limit);
$result = pg_exec($db, $sql);
$rows = pg_fetch_all($result);
echo json_encode($rows);
}
If you remove LIMIT from the query (REMOVE THIS . " LIMIT " . $limit . " OFFSET ". ($offset * $limit);), then there are two options:
Instead of pg_fetch_all you could fetch in a loop and specify the $row_num based on offset and limit:
//get total number of rows
$total = pg_num_rows($result);
//get rows from offset up to limit
$row_num = $offset;
while($row_num < ($offset + $limit) && $rows[] = pg_fetch_assoc($result, $row_num)) {
$row_num++;
}
echo json_encode($rows);
Or pg_fetch_all and slice what you want:
//get total number of rows
$total = pg_num_rows($result);
//get ALL rows
$rows = pg_fetch_all($result);
//get rows from offset up to limit
$rows = array_slice($rows, $offset, $limit);
echo json_encode($rows);
Not sure what new { records, total } does in .NET, but you could return one of these:
return json_encode([$rows, $total]);
//or
return json_encode(['rows' => $rows, 'total' => $total]);

Passing ID value from one table to another from drop down selection

What am I missing?
I have a drop down with values. I think everything is working fine, except when I post the results to another table I can't seem to get the gameID from the first table to post, it just goes through as blank. Am I missing an association with the team and the gameID?
Query to get data for drop down:
$sql = "select s.*, (DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > gameTimeEastern or DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > '" . $cutoffDateTime . "') as expired ";
$sql .= "from " . DB_PREFIX . "schedule s ";
$sql .= "inner join " . DB_PREFIX . "teams ht on s.homeID = ht.teamID ";
$sql .= "inner join " . DB_PREFIX . "teams vt on s.visitorID = vt.teamID ";
$sql .= "where s.weekNum = " . $week . " ";
$sql .= "order by s.gameTimeEastern, s.gameID";
//echo $sql;
$query = $mysqli->query($sql) or die($mysqli->error);
if ($query->num_rows > 0) {
$i = 0;
while ($row = $query->fetch_assoc()) {
$sGameID = (int)$row['gameID'];
$homeTeam = new team($row['homeID']);
$visitorTeam = new team($row['visitorID']);
$surv_pick_options_h[$i]=$row['homeID'];
$surv_pick_options_v[$i]=$row['visitorID'];
if ($row['expired']){
$surv_pick_expired_h[$i]=$row['homeID'];
$surv_pick_expired_v[$i]=$row['visitorID'];
}
$surv_gameID[$i] = (int)$row['gameID'];
$i++;
$rowclass = (($i % 2 == 0) ? ' class="altrow"' : '');
}
};
Drop down select option:
$sWeek = (int)getCurrentWeek()+1;
if ($week < $sWeek){
$survpicks_to_disable = array_slice($survpicks,0,$week-1);
$disabled = array_merge($survpicks_to_disable,$surv_pick_expired_h,$surv_pick_expired_v);
echo '<select name="survpick" id="survpick">
<option default>Select</option>';
foreach($surv_pick_options_h as $home){
echo '<option value="'.$home.'"'.(in_array($home,$disabled)?' style="background-color:pink" disabled':'').($home == $currentID?' selected':'').'>'.$home.'</option>';
}
foreach($surv_pick_options_v as $visitor){
echo '<option value="'.$visitor.'"'.(in_array($visitor,$disabled)?' style="background-color:pink" disabled':'').($visitor == $currentID?' selected':'').'>'.$visitor.'</option>';
}
}
echo '</select>';
}
And finally update a table with results:
$sql = "insert into " . DB_PREFIX . "picksurvivor (weekNum, userID, user, gameID, picksurv, showPicks) values (" . $_POST['week'] . ", " . $user->userID . ",'" . $user->userName . "', '" . $surv_gameID . "', '" . $_POST['survpick'] . "', ". (int)$_POST['showPicks'] . ");";
$mysqli->query($sql) or die('Error deleting survivor pick: ' . $mysqli->error);
I found a different approach, doing an update after the insert to basically brute force the gameID in there.

PHP Pagination for MySQL database - display the first page by default

Code:
$totalItemsRequired = 8;
$query = "SELECT * FROM fruits ORDER BY origin ASC ";
$result = mysqli_query($connection, $query);
if ($result == false)
{
echo "<p>Selecting all fruits failed.</p>";
}
else
{
$totalRecords = mysqli_num_rows($result);
$totalPages = ceil($totalRecords / $totalItemsRequired);
echo "<p>Page: ";
for ($i = 1; $i <= $totalPages; $i++)
{
echo "<a href='?page=" . $i . "'>" . $i . "</a> ";
}
echo "</p>";
if (isset($_GET['page']))
{
$currentPageNum = $_GET['page'];
$offset = ($currentPageNum - 1) * $totalItemsRequired;
$query = "SELECT * FROM fruits " . "LIMIT " . $offset . ", " . $totalItemsRequired;
$result = mysqli_query($connection, $query);
if ($result == false)
{
echo "<p>Selecting subset (page) of fruits failed.</p>";
}
else
{
echo "<ul>";
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
echo "<li>" . $row["id"] . "," . $row["name"] . ", " . $row["origin"] . ", " . $row["stock"] . "</li>";
}
echo "</ul>";
}
}
else
{
echo
// By default, load first page of records here
}
}
?>
Hi, I'm trying to load the first page of records by default where I have put the comment. There are no problems with the code, and the initial output is good. I'm just not sure how to show by default. Can anyone help please?
EDIT: Can anyone help?
Why not use LIMIT clause in your MySQL statement?
SELECT * FROM fruits ORDER BY origin ASC LIMIT 8 //First 8 rows of the table
SELECT * FROM fruits ORDER BY origin ASC LIMIT 8,8 //Second 8 rows
SELECT * FROM fruits ORDER BY origin ASC LIMIT 16,8 //Third 8 rows
In General:
LIMIT offset,row_count will return row_count rows starting from offset+1 row.
Instead of if statement, you should just be able to change
$currentPageNum = $_GET['page'];
$offset = ($currentPageNum - 1) * $totalItemsRequired;
to
$currentPageNum = isset($_GET['page']) ? $_GET['page'] : 0;
$offset = $currentPageNum > 0 ? (($currentPageNum - 1) * $totalItemsRequired) : 0;
Full code:
<?php
$totalItemsRequired = 8;
$query = "SELECT * FROM fruits ORDER BY origin ASC ";
$result = mysqli_query($connection, $query);
if ($result == false)
{
echo "<p>Selecting all fruits failed.</p>";
}
else
{
$totalRecords = mysqli_num_rows($result);
$totalPages = ceil($totalRecords / $totalItemsRequired);
echo "<p>Page: ";
for ($i = 1; $i <= $totalPages; $i++)
{
echo "<a href='?page=" . $i . "'>" . $i . "</a> ";
}
echo "</p>";
$currentPageNum = isset($_GET['page']) ? $_GET['page'] : 0;
$offset = $currentPageNum > 0 ? (($currentPageNum - 1) * $totalItemsRequired) : 0;
$query = "SELECT * FROM fruits " . "LIMIT " . $offset . ", " . $totalItemsRequired;
$result = mysqli_query($connection, $query);
if ($result == false)
{
echo "<p>Selecting subset (page) of fruits failed.</p>";
}
else
{
echo "<ul>";
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
echo "<li>" . $row["id"] . "," . $row["name"] . ", " . $row["origin"] . ", " . $row["stock"] . "</li>";
}
echo "</ul>";
}
}
}
?>

Calculating total of rows

I fetching and displaying records from database like this
SELECT purchorders.orderno,
suppliers.suppname,
purchorders.orddate,
purchorders.deliverydate,
purchorders.initiator,
purchorders.requisitionno,
purchorders.allowprint,
purchorders.status,
suppliers.currcode,
currencies.decimalplaces AS currdecimalplaces,
SUM(purchorderdetails.unitprice*purchorderdetails.quantityord) AS ordervalue
FROM purchorders
INNER JOIN purchorderdetails
ON purchorders.orderno = purchorderdetails.orderno
INNER JOIN suppliers
ON purchorders.supplierno = suppliers.supplierid
INNER JOIN currencies
ON suppliers.currcode=currencies.currabrev
WHERE purchorders.orderno=purchorderdetails.orderno
GROUP BY purchorders.orderno,
suppliers.suppname,
purchorders.orddate,
purchorders.initiator,
purchorders.requisitionno,
purchorders.allowprint,
purchorders.status,
suppliers.currcode,
currencies.decimalplaces LIMIT 5
I am getting the result properly. But i want to calculate and display the result of ordervalues which i have displayed (total of all 5 as i limit it to 5)
I tried doing like this
$SalesOrdersResult2 = DB_query($SQL,$db);
while ($row = DB_fetch_array($SalesOrdersResult2))
{
$FormatedOrderValue2 = locale_number_format($row['ordervalue'],$row['currdecimalplaces']);
$Total = $array_sum($row['ordervalue']);
$FormatedOrderDate1 = ConvertSQLDate($row['orddate']);
$FormatedDelDate1 = ConvertSQLDate($row['deliverydate']);
echo " <tr><td> " . $row['suppname'] . " </td>";
echo " <td>$FormatedOrderDate1</td><td>$FormatedDelDate1</td><td> " . $row['initiator'] . " </td><td>$FormatedOrderValue2</td><td> " . $row['status'] . " </td></tr> ";
}
echo "<tr><td colspan='3'>Total---</td><td colspan='2'>$Total</td></tr></tbody>";
But it says "Fatal error: Function name must be a string in ..."
Somebody please help me in doing this
Thanks
I suspect you're trying to do something like this?:
$SalesOrdersResult2 = DB_query($SQL, $db);
$Total = 0;
while ($row = DB_fetch_array($SalesOrdersResult2))
{
$FormatedOrderValue2 = locale_number_format($row['ordervalue'],$row['currdecimalplaces']);
$Total += $row['ordervalue'];
$FormatedOrderDate1 = ConvertSQLDate($row['orddate']);
$FormatedDelDate1 = ConvertSQLDate($row['deliverydate']);
echo " <tr><td> " . $row['suppname'] . " </td>";
echo " <td>$FormatedOrderDate1</td><td>$FormatedDelDate1</td><td> " . $row['initiator'] . " </td><td>$FormatedOrderValue2</td><td> " . $row['status'] . " </td></tr> ";
}
echo "<tr><td colspan='3'>Total---</td><td colspan='2'>$Total</td></tr></tbody>";
Remove the $ before array_sum.

Categories