mysqli_fetch_array iteration issue - php

I have a page that is dynamically generated using PHP and a MySQL database. The page displays information about an event, and lists the dates that event will run.
My database has the following relevant tables:
events - containing the event name, cost etc
venue - containing venue information
instance - containing the event_id, venue_id, the date the event at that venue will run, and the capacity for that instance.
registration - containing the instance_id, and attendee_id.
To grab all the information to actually display the event information, I use the following code:
$eid = $_GET['event_id'];
$q = "SELECT e.event_name, e.event_description, e.event_byline, e.event_benefit, e.event_cost, e.event_exam, e.event_resi, i.venue_id, i.instance_id, i.instance_cap, v.venue_name, DATE_FORMAT( i.instance_date, '%M %D, %Y' ) AS DATE
FROM events AS e
INNER JOIN instance AS i ON e.event_id = i.event_id
INNER JOIN venue AS v ON i.venue_id = v.venue_id
WHERE e.event_id = $eid
ORDER BY i.venue_id, i.instance_date";
$cur_venue = 0;
$r = #mysqli_query ($dbc,$q) or die(mysqli_error($dbc));
$row = mysqli_fetch_array($r, MYSQLI_ASSOC);
Now, what I want to do is display a list, sorted by venue, of the instances for the relevant event, which I have done up to a point. However, what I also want to do is only display the instance if there is space left on that particular instance.
Since I know the capacity of each instance (from my instance_cap column), and I can COUNT the number of attendees registered to each instance, I figure I can do this thuswise:
do
{
$list_instance = $row['instance_id'];
$qRegs = "SELECT COUNT(delegate_id) AS regs FROM registration
WHERE registration.instance_id = $list_instance";
$rRegs = mysqli_query($dbc,$qRegs);
$registrations = mysqli_fetch_object($rRegs);
$capacity = $row['instance_cap'];
$availability = $capacity - $registrations->regs;
if ($availability > 0){ //if event has places available...
if ($cur_venue != $row['venue_id']) //and if the current venue is not the same as the venue id
{
echo '<li id="'.$row['venue_name'].'">'
$cur_venue = $row['venue_id'];
echo '<h4>'.$row['venue_name'].'</h4>';//display the venue name
}
echo ''.$row['DATE'].'' //display the date for current instance
echo '</li>';//close list tag
}
} while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC));';
The problem I have is that this misses out the first instance and skips straight to the second one. I understand that this is probably due to the fact that I have called mysqli_fetch_array twice, so how I can work it so that this doesn't happen?

You should be able to run one query, and then just use the resultset. Try this:
SELECT e.event_name, e.event_description, e.event_byline,
e.event_benefit, e.event_cost, e.event_exam, e.event_resi,
i.venue_id, i.instance_id, i.instance_cap, v.venue_name,
DATE_FORMAT( i.instance_date, '%M %D, %Y' ) AS DATE
FROM events AS e
INNER JOIN instance AS i ON e.event_id = i.event_id
INNER JOIN venue AS v ON i.venue_id = v.venue_id
WHERE e.event_id = $eid AND i.instance_cap > (SELECT COUNT(r.delegate_id) FROM registration AS r WHERE r.instance_id = i.instance_id)
ORDER BY i.venue_id, i.instance_date
Granted, this is untested, so it might not work as-is.
EDIT: a sub-query is probably more correct. See the edited query above.

Put
mysqli_data_seek ( $r , 0 );
before the second mysqli_fetch_array to reset the internal pointer to the first instance.

Related

How to list records by date?

you see I am trying to list the records of a table in my database, but I want to do it in the following way:
First, it has to display the date
and then all the records on that date should appear
In my table of the database I have 4 fields:
id, task, date, time
For example there are multiple tasks that are performed in a day, but at different times. Then I have stored in my database many tasks of different days and in different hours. What I want is to list them per day. Consult the database and show a list where the date appears first and then all the tasks that were done on that date, then show the other date and then all the tasks of that date and so on.
Something like that
That's my php code
$obj = new Task();
$consult = $obj->Lists();
date_default_timezone_set("America/Mexico_City");
$dateActual = date("Y-m-d");
while ($result = $consult->fetch_object()) {
echo "<button class='btn btn-default'>date = " . $result->date . "</button><br>";
$consult2 = $obj->Lists2($dateActual);
while($result2 = $consult2->fetch_object()) {
echo "<span>". $result2->time ."</span><br>";
}
$dateActual = $result->date;
}
my query to the database is:
public function Lists2($date)
{
global $conexion;
$sql = "SELECT ar.*, date_format(ar.date, '%d/%m/%Y') as date,
date_format(ar.time, '%r') as time,
u.user as User
FROM task_recents ar
INNER JOIN user u ON ar.iduser = u.iduser
WHERE date = '$date'
ORDER BY ar.time DESC";
$query = $conexion->query($sql);
return $query;
}
public function Lists()
{
global $conexion;
$sql = "SELECT ar.*, date_format(ar.date, '%d/%m/%Y') as date,
date_format(ar.time, '%r') as time,
u.user as User
FROM task_recents ar
INNER JOIN user u ON ar.iduser = u.iduser
ORDER BY ar.time DESC";
$query = $conexion->query($sql);
return $query;
}
The result is that it shows me the repeated date with their respective records.
What I'm trying to achieve is something like this:
How could I do it?
PD: The result that I'm getting is this:
But I don't like that...
The INNER JOIN keyword selects all rows from both tables as long as there is a match between the columns. If there are records in the "Orders" table that do not have matches in "Customers", these orders will not be shown!
The following query should no longer generate duplicate records
SELECT
ar.id,
ar.task,
date_format(ar.date, '%d/%m/%Y') as formattedDate,
date_format(ar.time, '%r') as formattedTime,
u.user as User
FROM
task_recents ar
LEFT JOIN
user u
ON
u.iduser = ar.iduser
WHERE
date = '$date'
ORDER BY
ar.time
DESC

The same response for the second table

i am having a problem with my code. I am having the same response for my second table. While in the first one it goes to the next column.
PHP
$sql = "SELECT * from schedule s, matches m GROUP BY s.id";
$con = mysqli_connect($server_name,$mysql_user,$mysql_pass,$db_name);
$result = mysqli_query($con,$sql);
$response = array();
while($row=mysqli_fetch_array($result))
{
array_push($response, array("start"=>$row[4],"end"=>$row[5],"venue"=>$row[6], "teamone"=>$row[8], "teamtwo"=>$row[9],
"s_name"=>$row[17]));
}
echo json_encode (array("schedule_response"=>$response));
mysqli_close($con);
?>
Here is the response i am getting. As you can see the teamone, teamtwo and s_name are all the same. It does not get the value of the second column.
{"schedule_response":[
{"start":"2016-11-23 00:00:00","end":"2016-11-24 00:00:00","venue":"bbbb",
"teamone":"aaa","teamtwo":"hehe","s_name":"sssss"},
{"start":"2016-11-22 00:00:00","end":"2016-11-23 00:00:00","venue":"aaaaaaa",
"teamone":"aaa","teamtwo":"hehe","s_name":"sssss"}]}
Schedule table
Matches Table
You can define the m_id in query
$sql = "SELECT * from schedule as s, matches as m where s.m_id = m.m_id GROUP BY s.id";
To make sure you get "some answer" even if no data is properly linked, you need to us LEFT JOIN:
SELECT *
FROM schedule s
LEFT JOIN matches m ON s.m_id=m.m_id
In this context GROUP BY might be unnecessary. Depends how your data is structured

Generate html table based on 2x mysql db queries

I'm trying to show stuff queried from two tables, but on one html table. Data is shown for the last 30 days, based on which, an html table is being generated.
Currently I'm stuck using two queries and generating two html tables:
$query1 = mysqli_query( $con, "SELECT date, stuff* " );
while( $record = mysqli_fetch_array( $query1 ) ){
echo '<html table generated based on query>';
}
$query2 = mysqli_query( $con, "SELECT date, other stuff*" );
while( $record = mysqli_fetch_array( $query2 ) ){
echo '<another html table generated based on query2>';
}
Is there a possibility to show both queries on one html table instead?
Note that it gets tricky since we have dates on one table which are not necessarily found in the second table or vice-versa.
Thanks for the support guys. So far I'm stuck at this:
SELECT * FROM user_visit_logs
LEFT JOIN surfer_stats ON user_visit_logs.date = surfer_stats.date
UNION
SELECT * FROM user_visit_logs
RIGHT JOIN surfer_stats ON user_visit_logs.date = surfer_stats.date
The query completes, but the 2nd table fields are all null:
Furthermore, it breaks when I add additional clause like:
WHERE user_id = '{$_SESSION['user_id']}' ORDER BY date DESC LIMIT 30
I think you are after FULL OUTER JOIN concept:
The FULL OUTER JOIN keyword returns all rows from the left table (table1) and from the right table (table2)
In which you may use common dates as a shared row.
So the query will get to simple one:
$query = "
SELECT table1.date, stuff
FROM table1
LEFT OUTER JOIN table2 ON table1.date = table2.date
UNION
SELECT table2.date, other_stuff
FROM table1
RIGHT OUTER JOIN table2
ON table1.date = table2.date
";
$result = mysqli_query( $con, $query );
while( $record = mysqli_fetch_array( $result ) ){
echo '<html table generated based on query>';
}
Example
This is an schematic diagram of FULL OUTER JOIN concept:
After running into quite a few bumps with this one, I finally managed to merge 2 columns from each table and also to use where and sort clauses on them with the following query:
( SELECT user_visit_logs.user_id,user_visit_logs.date,unique_hits,non_unique_hits,earned,sites_surfed,earnings FROM user_visit_logs
LEFT OUTER JOIN surfer_stats ON user_visit_logs.user_id = surfer_stats.user_id AND user_visit_logs.date = surfer_stats.date where user_visit_logs.user_id = 23 ORDER BY date DESC LIMIT 30 )
UNION
( SELECT surfer_stats.user_id,surfer_stats.date,unique_hits,non_unique_hits,earned,sites_surfed,earnings FROM user_visit_logs
RIGHT OUTER JOIN surfer_stats ON user_visit_logs.user_id = surfer_stats.user_id AND user_visit_logs.date = surfer_stats.date where user_visit_logs.user_id = 23 LIMIT 30 )
Simplified, "user_visit_logs" and "surfer_stats" were the 2 tables needed to be joined.
Absolutely. Just pop them both into a variable:
$data = '';
$query = mysqli_query($con,"SELECT date, stuff* ");
while($record = mysqli_fetch_array($query)) {
$data.= '<tr><td>--Your Row Data Here--</td></tr>';
}
$query2 = mysqli_query($con,"SELECT date, other stuff*");
while($record = mysqli_fetch_array($query2)) {
$data .= '<tr><td>--Your Row Data Here--</td></tr>';
}
echo "<table>$data</table>";
Instead of using echo in your loop, you're just storing the results in $data. Then, you're echoing it out after all data has been added to it.
As for your second point, it's not a big deal if fields don't exist. If they're null, you'll just have a column that doesn't have data in it.
Here's an example with fake column names:
$data = '';
$query = mysqli_query($con,"SELECT date, stuff* ");
while($record = mysqli_fetch_array($query)) {
$data.= "<tr><td>{$record[id]}</td><td>{$record[first_name]}</td><td>{$record[last_name]}</td></tr>";
}
$query2 = mysqli_query($con,"SELECT date, other stuff*");
while($record = mysqli_fetch_array($query2)) {
$data .= "<tr><td>{$record[id]}</td><td>{$record[first_name]}</td><td>{$record[last_name]}</td></tr>";
}
echo "<table><tr><th>ID</th><th>First Name</th><th>Last Name</th></tr>$data</table>";
I have a feeling I may have misunderstood the need. If so, I apologize. If you can elaborate just a bit more I can change my answer :)

PHP not storing query result

For a particular query
SELECT MAX(theCount), day
FROM (SELECT FK_Hour, day As day, Count(FK_Hour) As theCount
FROM (Select slottime.FK_Hour, time.day
From slottime INNER JOIN time ON slottime.FK_Hour = time.Hour )
As C GROUP By FK_Hour
)
AS counts GROUP By day
The database returns
However when running the php code
$timequery = array();
try {
$sth = $dbh->prepare("SELECT MAX(theCount), day
FROM (SELECT FK_Hour, day As day, Count(FK_Hour) As theCount
FROM (Select slottime.FK_Hour, time.day
From slottime INNER JOIN time ON slottime.FK_Hour = time.Hour )
As C GROUP By FK_Hour
)
AS counts GROUP By day
");
$sth->execute();
while ($timequery = $sth->fetch(PDO::FETCH_ASSOC)) {
$timequery[] = $results;
}
echo("trying ");
print_r($timequery);
echo(" tried");
}
The output is merely
trying tried
$results seem to be uninitialized... Change code as shown below
while ($results = $sth->fetch(PDO::FETCH_ASSOC))

MySQL/PHP: Multiple AND/OR tags in SELECT from two tables

I've got two tables, customer and reservations. customer and reservations both contain a row called customerID. reservations contains two columns named resStart and resEnd that only have dates in them (YYYY-MM-DD, which is the exact format I'll be using to establish the $todaysdate variable.
I'd like to join those two to produce a table with single column of customerID along with other info, but only if $todaysdate falls on or between two dates. Note: $todaysdate is established elsewhere in my documents as either a _GET from url (ie. day.php?date=2012-07-04) or if none is established, today's date with date('Y-m-d'). This part of the code is not where my problems are lying, I'm sure of that. I'm thinking it's a syntax error somewhere while defining the information in the mySql query.
Here's what I'm working with. A little explanation: I'm wrapping PHP code around Javascript, and the goal here is to produce a separate DIV for each resStart. The Javascript is fetching offset variables to add to the CSS of each DIV, so each DIV is automatically placed relative to the equipment it's representing.
<?php
$getreservations = mysql_query("
SELECT * FROM customer LEFT JOIN reservations WHERE ( customer.customerID = reservations.customerID )
AND ($todaysdate = resStart OR $todaysdate >= resStart AND $todaysdate <= resEnd )
")
or die(mysql_error());
while( false !== ($row = mysql_fetch_assoc($getreservations)))
{
$nameLast = $row["nameLast"];
$nameFirst = $row["nameFirst"];
$customerID = $row["customerID"];
$equipID = $row["equipID"];
$resStart = $row["resStart"];
$resEnd = $row["resEnd"];
$timeStart = $row["timeStart"];
$timeEnd = $row["timeEnd"];
$result = strtotime($timeStart);
$minute = date("i", $result );
$second = date("s",$result );
$hour = date("H", $result );
if(true) {
?>
<script language='javascript'>
var left = $('#<?php echo("$hour$minute");?>').offset().left;
var top = $('#<?php echo $equipID;?>').offset().top;
$(document).ready(function() {
$('#<?php echo ("$customerID$equipID");?>).css( { 'left': (pos.left + width) + 'px', 'top': (pos.top + top) + 'px' } );
}
</script>
<?php }
echo ("<div class='resContainer $customerID$equipID' id=$customerID$equipID>$nameLast, $nameFirst</div> ");
} ?>
SELECT * FROM customer c INNER JOIN reservations r USING(customerID) WHERE '{$todaysdate}' BETWEEN r.resStart AND r.resEnd
However, You can also get the "todaysdate" in SQL: DATE(NOW()), and the statement will be:
SELECT * FROM customer c INNER JOIN reservations r USING(customerID) WHERE DATE(NOW()) BETWEEN r.resStart AND r.resEnd
EDIT: added quotes around $todaysdate variable to avoid confusion
Try your query directly in database first. You'll get proper error code and the information, where the problem is.
When using JOIN, you should specify the join condition, with USING or ON (table1.field=table2.field). (ref to doc: http://dev.mysql.com/doc/refman/5.0/en/join.html)
Try below query:
SELECT * FROM customer
LEFT JOIN reservations on customer.customerID = reservations.customerID
WHERE curdate() BETWEEN r.resStart AND r.resEnd

Categories