I'm trying to do two separate database quires and return the results to a form. Each result is written to a table.
I want to be able to combine the two queries into one and order the results by task number.
FIRST QUERY:
//Booking
$Date= date("d/m/Y");
$driver = $_SESSION['username'];
$dbTaskRecords = "SELECT * FROM booking WHERE driver='$driver' AND Date= CAST('$Date_search' AS DATE) ORDER BY TaskNo ASC";
$dbTaskRecords_result = mysql_query($dbTaskRecords);
SECOND QUERY:
//Return Booking
$dbTaskReturn = "SELECT * FROM returnbooking WHERE driver='$driver' AND Date= CAST('$Date_search' AS DATE) ORDER BY TaskNo ASC";
$dbTaskReturn_result = mysql_query($dbTaskReturn);
The results are then outputted to the page through a while statement.
$i=0;
while ($row = mysql_fetch_array($dbTaskRecords_result)){
//Control Structure for Move Time on first Job of day
if ($i==0 ){
$time = $row["Time"];
//$time = 'N/A';
}else{
$time = 'N/A';
}
//Get Rego from trucks table
$truckID = $row["TruckID"];
$Rego_select = mysql_query("SELECT VechicleRegistration FROM trucks WHERE TruckID = '$truckID'" )
or die("Problem reading table: " . mysql_error());
$Rego = mysql_result($Rego_select,0);
//Get unregisted from trucks table
$Unregisted_select = mysql_query("SELECT Unregistered FROM trucks WHERE TruckID = '$truckID'" )
or die("Problem reading table: " . mysql_error());
$Unregisted = mysql_result($Unregisted_select,0);
$id_note = $row["BookingID"];
echo '<td><a href="taskpage.php?id='.$id_note.'"><button>'. $row['TaskNo']."</button><a/></td>";
echo "<td>". $time . "</td>"; // Time Frame
echo "<td>". $Unregisted."</td>"; // Pickup
echo "<td>". $Rego."</td>"; // Unregisted
echo "<td>".$row["PickupLocation"] . "</td>"; // Rego
echo "<td>".$row["DropOffLocation"] . "</td></tr>"; // Delivery
$i=$i+1;//Control Set
}
echo'</tr>';
I repeat this same output code for the results from the return booking.
Is it possible to combine both queries into one so that the result set from both tables can be ordered by ASC and outputted by the above while statement.
This is one of the many reasons to avoid Select *. You can simply use a union
Select Time, TruckId, TaskNo, PickupLocation, DropOffLocation
From booking
Where driver='$driver'
And Date= CAST('$Date_search' AS DATE)
Union All
Select Time, TruckId, TaskNo, PickupLocation, DropOffLocation
From returnbooking
WHERE driver='$driver'
And Date= CAST('$Date_search' AS DATE)
Order By TaskNo Asc
In this solution, you need to enumerate the columns and ensure that the type of the columns, in the order in which they are enumerated in the two Select clauses are identical.
From what I can tell you have three options to accomplish what you are after.
You could use a join, assuming the two tables have a foreign key.
You could use a union to append the two result sets.
You could output both queries into an array and iterate through that array for your output. This is probably less efficient then a union, but gives you greater separation between the two result sets.
Using multiple smaller tables keep your data organized and ensures the column names are the same.
If we have for instance a company with a bunch of customers, and where customers could be private clients or companies, using a seperate table for those adresses and 2 reference tables with either client_id and adres_id or company_id and adres_id, the adres will always have the same column names.
Not only that, but if certain information is limited you don't run the risk of storing empty space...
In the end you should really stick to SQL for getting ALL the data you need in one go and use PHP (or other server side scripts) for formatting this data to the user. It isn't much of a problem for an internal or private website, but when you have more users you will want to limit the amount and size of your data transfers.
Using only 1 long query is often better than several smaller.
Related
I have updated my original post based on what I learned from your comments below. It is a much simpler process than I originally thought.
require '../database.php';
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM Orders WHERE id = 430";
$q = $pdo->prepare($sql);
$q->execute(array($id));
$data = $q->fetch(PDO::FETCH_ASSOC);
echo 'Order Num: ' . $data['id'] . '<br>';
$sql = "SELECT * FROM Order_items
JOIN Parts ON Parts.id = Order_Items.part_id
WHERE Order_Items.orders_id = 430";
$q = $pdo->prepare($sql);
$q->execute(array($line_item_id));
$data = $q->fetch(PDO::FETCH_ASSOC);
while ($data = $q->fetch(PDO::FETCH_ASSOC))
{
echo '- ' . $data['part_num'] . $data['qty'] . "<br>";
}
Database::disconnect();
Unfortunately, only my first query is producing results. The second query is producing the following ERROR LOG: "Base table or view not found: 1146 Table 'Order_items' doesn't exist" but I am expecting the following results.
Expected Results from Query 1:
Order Num: 430
Expected Results from Query 2:
- Screws 400
- Plates 35
- Clips 37
- Poles 7
- Zip ties 45
Now that I understand where you are coming from, let's explain a couple of things.
1.PDO and mysqli are two ways of accessing the database; they essentially do the same things, but the notation is different.
2.Arrays are variables with multiple "compartments". Most typical array has the compartments identified by a numerical index, like:
$array[0] = 'OR12345'; //order number
$array[1] = '2017-03-15'; //order date
$array[2] = 23; //id of a person/customer placing the order
etc. But this would require us to remember which number index means what. So in PHP there are associative arrays, which allow using text strings as indexes, and are used for fetching SQL query results.
3.The statement
$data = $q->fetch(PDO::FETCH_ASSOC)
or
$row = $result->fetch_assoc()
do exactly the same thing: put a record (row) from a query into an array, using field names as indexes. This way it's easy to use the data, because you can use field names (with a little bit around them) for displaying or manipulating the field values.
4.The
while ($row = $result->fetch_assoc())
does two things. It checks if there is a row still to fetch from the query results. and while there is one - it puts it into the array $row for you to use, and repeats (all the stuff between { and }).
So you fetch the row, display the results in whatever form you want, and then loop to fetch another row. If there are no more rows to fetch - the loop ends.
5.You should avoid using commas in the FROM clause in a query. This notation can be used only if the fields joining the tables are obvious (named the same), but it is bad practice anyway. The joins between tables should be specified explicitly. In the first query you want the header only, and there is no additional table needed in your example, so you should have just
SELECT *
FROM Orders
WHERE Orders.Order_ID = 12345
whereas in the second query I understand you have a table Parts, which contains descriptions of various parts that can be ordered? If so, then the second query should have:
SELECT *
FROM Order_items
JOIN Parts ON Parts.ID = Order_Items.Part_ID
WHEERE Order_Items.Order_ID = 12345
If in your Orders table you had a field for the ID of the supplier Supplier_ID, pointing to a Suppliers table, and an ID of the person placing the order Customer_ID, pointing to a Customers table, then the first query would look like this:
SELECT *
FROM Orders
JOIN Suppliers ON Suppliers.ID = Orders.Supplier_ID
JOIN Customers ON Customers.ID = Orders.Customer_ID
WHERE Orders.Order_ID = 12345
Hope this is enough for you to learn further on your own :).
Basically, I'm coding a site that has many different categories and I want to display the amount of rows specific to that ID.
So for example, I have as the query:
$query= "SELECT job_sec FROM jobs WHERE job_sec = ?";
mysqli_num_rows($query);
I need to know how I can count the rows of an ID then echo the rows counted.
I'd like the results to display:
Web Design: 2,001 jobs
Logo Design: 5,120 Jobs
The job_sec column just uses a numerical value, would it be easier to have a text value then count the rows relating to the text value and echo them?
I have a feeling I need to use an array however I need the most efficient method.
Any help would be much appreciated!
Assuming job_sec is the category and I think you are looking for "group by":
$sql= "SELECT job_sec, count(*) AS c FROM jobs GROUP BY job_sec";
$r = mysqli_query($sql);
while ($row = mysqli_fetch_assoc($r)) {
echo $row['job_sec'] . ': ' . $row['c'] . ' Jobs ';
}
(didn't test and not sure if the mysqli syntax is correct)
Quite a complex question:
At the moment I have a table called "timetable". This is updated when someone books a slot (this is for a radio booking system). What I would like is a PHP file that I can have run every 15 minutes as a cron job. In PHP script what I'd like it to do is count how many slots a radio presenter has booked via the "username" field in the "timetable" table. Then I would like it to update a field in another table called "users" in a field called "slot_count" with the amount of slots which were found in the "timetable" table under their "username".
At the moment I have a script which pulls all the booked slots with their presenter "username"'s into a table:
<?php
include("../config.php");
include("functions.php");
if($logged["level"] == "HDJ" OR $logged["level"] == "SA") {
echo "<table width=\"580px\" class=\"board\" border=\>";
$order = "SELECT * FROM timetable WHERE username <> 'No DJ'";
$result = mysql_query($order);
// Error checking
if (!$result) {
// output error, take other action
}
else {
while ($row=mysql_fetch_array($result)){
// Append all results onto an array
$rowset[] = $row;
}
}
foreach ($rowset as $row) {
echo "<tr><td>" . htmlspecialchars($row['username']) . "</td></tr>";
}
} else {
echo ("<div class=\"caution\">Access is denied.</div>");
}
?>
Any ideas?
Storing this redundant data in your users table is unnecessary. As long as the tables are indexed appropriately the join and count are trivial -
SELECT users.*, COUNT(timetable.username) AS num_slots
FROM users
LEFT JOIN timetable
ON users.username = timetable.username
GROUP BY users.id
Can't it be done using one sql statement doing both COUNT() and UPDATE:
UPDATE users
SET slot_count = (SELECT COUNT(*) FROM timetable WHERE timetable.username = users.username)
Assumption: the username field contains the same value for the same radio presenter in both users and timetable tables. Otherwise they wouldn't match. You should be able to run this query directly against MySQL from the cron job (instead of doing the PHP script).
Hey guys, I created a list for fixtures.
$result = mysql_query("SELECT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' GROUP BY date");
$i = 1;
$d = "Start";
while ($row = mysql_fetch_assoc($result))
{
$odate = $row['date'];
$date=date("F j Y", $row['date']);
echo "<p>Fixture $i - $d to $date</p>";
}
As you can see from the query, the date is displayed from the fixtures table.
The way my system works is that when a fixture is "played", it is removed from this table. Therefore when the entire round of fixtures are complete, there wont be any dates for that round in this table. They will be in another table.
Is there anyway I can run an other query for dates at the same time, and display only dates from the fixtures table if there isnt a date in the results table?
"SELECT * FROM ".TBL_CONF_RESULTS."
WHERE compid = '$_GET[id]' && type2 = '2' ORDER BY date"
That would be the second query!
EDIT FROM HERE ONWARDS...
Is there anyway I can select the date from two tables and then only use one if there are matches. Then use the rows of dates (GROUPED BY) to populate my query? Is that possible?
It sounds like you want to UNION the two result sets, akin to the following:
SELECT f.date FROM tbl_fixtures f
WHERE f.compname = '$comp_name'
UNION SELECT r.date FROM tbl_conf_results r
WHERE r.compid = '$_GET[id]' AND r.type2 = '2'
GROUP BY date
This should select f.date and add rows from r.date that aren't already in the result set (at least this is the behaviour with T-SQL). Apparently it may not scale well, but there are many blogs on that (search: UNION T-SQL).
From the notes on this page:
//performs the query
$result = mysql_query(...);
$num_rows = mysql_num_rows($result);
//if query result is empty, returns NULL, otherwise,
//returns an array containing the selected fields and their values
if($num_rows == NULL)
{
// Do the other query
}
else
{
// Do your stuff as now
}
WHERE compid = '$_GET[id]' presents an oportunity for SQL Injection.
Are TBL_FIXTURES and TBL_CONF_RESULTS supposed to read $TBL_FIXTURES and $TBL_CONF_RESULTS?
ChrisF has the solution!
One other thing you might think about is whether it is necessary to do a delete and move to another table. A common way to solve this type of challenge is to include a status field for each record, then rather than just querying for "all" you query for all where status = "x". For example, 1 might be "staging", 2 might be "in use", 3 might be "used" or "archived" In your example, rather than deleting the field and "moving" the record to another table (which would also have to happen in the foreach loop, one would assume) you could simply update the status field to the next status.
So, you'd eliminate the need for an additional table, remove one additional database hit per record, and theoretically improve the performance of your application.
Seems like what you want is a UNION query.
$q1 = "SELECT DISTINCT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name'";
$q2 = "SELECT DISTINCT date FROM ".TBL_CONF_RESULTS.
"WHERE compid = '$_GET[id]' && type2 = '2'";
$q = "($q1) UNION DISTINCT ($q2) ORDER BY date";
Alright, so I have a table outputting data from a MySQL table in a while loop. Well one of the columns it outputs isn't stored statically in the table, instead it's the sum of how many times it appears in a different MySQL table.
Sorry I'm not sure this is easy to understand. Here's my code:
$query="SELECT * FROM list WHERE added='$addedby' ORDER BY time DESC";
$result=mysql_query($query);
while($row=mysql_fetch_array($result, MYSQL_ASSOC)){
$loghwid = $row['hwid'];
$sql="SELECT * FROM logs WHERE hwid='$loghwid' AND time < now() + interval 1 hour";
$query = mysql_query($sql) OR DIE(mysql_error());
$boots = mysql_num_rows($query);
//Display the table
}
The above is the code displaying the table.
As you can see it's grabbing data from two different MySQL tables. However I want to be able to ORDER BY $boots DESC. But as its a counting of a completely different table, I have no idea of how to go about doing that.
There is a JOIN operation that is intended to... well... join two different table together.
SELECT list.hwid, COUNT(log.hwid) AS boots
FROM list WHERE added='$addedby'
LEFT JOIN log ON list.hwid=log.hwid
GROUP BY list.hwid
ORDER BY boots
I'm not sure if ORDER BY boots in the last line will work like this in MySQL. If it doesn't, just put all but the last line in a subquery.
But the result of the query into an array indexed by $boots.
AKA:
while(..){
$boot = mysql_num_rows($query);
$results[$boot][] = $result_array;
}
ksort($results);
foreach($results as $array)
{
foreach($array as ....)
{
// display table
}
}
You can switch between ksort and krsort to switch the orders, but basically you are making an array that is keyed by the number in $boot, sorting that array by that number, and then traversing each group of records that have a specific $boot value.