I'm working in the IT department of my company and it is my responsibility to send daily reports of the calls registered in the Call Center department. I'm new with MySQL, PHP or HTML and I'm already facing my first problems.
My objective is to run some queries in PHP and then output them in a HTML table cell. Let me be more specific. I have access to a telephone record database and I need to count the number of total calls and lost calls of every branch daily. Right now I just run 2 queries in MySQL and then copy-paste them in a .xls table.
I have the right queries, I get the right result in mysql, even in PHP I get the result posted on the webpage (kind of), but I don't know how to create a table, or how to input the result of a query into a specific cell of the table.
Here's what I've got so far:
<?php
$conn=#mysql_connect('host', 'username', 'password', 'asteriskcdrdb.cdr');
echo ('total calls ROPCW: ');
$result=mysql_query('select count(*) from asteriskcdrdb.cdr where calldate like "2016-04-11%" and dst="020" and disposition="ANSWERED" and duration > "10" ');
echo mysql_result($result, 0);
mysql_close($conn);
?>
This code will post on my page the count of total calls made on 4.11.2016 like this:
total calls ROPCW: 369
My objective is to create a table like this:
So the result of that query I mentioned above would go on the ROPCW->Total cell (where is 305) on the left side, on the right side are the monthly reports so far.
You can work out one big query or use a view to gather the data you need from a single source. Other suggestion would be, looping through all your branches and gather all the data you need, to build an associative array indexed similar to this:
$records[branch] = [date => [total => x, lost => y], mtd => [total => X, lost => Y]];
Then just do a:
foreach ($records as $branch => $record)
{
echo string to build table row
}
I suggest use mysql_fetch_object or mysql_fetch_assoc functions instead of mysql_result. Basically because those functions fetch an entire row instead of one single cell value. For your example query works fine because your aggregate function returns only one cell and row. But for your desired output won't work.
Keep in mind that you can inject HTML code within PHP and vice versa. Just do something like:
The idea would be run a select * from yourTable;
Then,
$result = mysql_query($sql);
echo "<table>\n";
echo "<tr><th>Branch</th></tr>\n";
while ($callRecord = mysql_fetch_object($result)) {
echo "<tr><td>{$callRecord->branch}</td></tr>\n";
}
echo "</tr>\n";
echo "</table>\n";
That should output a list of all tour branches. this is a guideline.
Hope this helps!!
You can go to www.php.net and choose between mysql_fetch functions which one will work better for you.
Related
I'm making a simple website using PHP and MySQL, where based on the entered criteria, the website outputs the results from the database. Since there'll be a lot of them (eventually, now there's like 6) I want to compress the table, by having two or three results next to each other. The results will be displayed as images (whose address is pulled from the database) within the table's cells, ideally with a title (also from the DB) under them.
Everywhere i've looked (like w3s or here), the code puts each pulled attribute of a table's row into its own cell, and each row of the html table corresponds to the sql table.
Specifically:
from the search form, i $_GET variables $color and $altmode
in my table 'transformers', i have columns 'id' (auto incrementing), 'color', 'altmode', 'name' and 'image1'
using PDO, I want to SELECT id,name,image1 FROM transformers WHERE color=$color AND altmode=$altmode; and have the results in one table.
basically like this except dynamically generated from the PDO query results, and with the name of each toy being listed under the image.
Honestly i don't know where to begin. So far I have this (with the $conn connection being initialised in required connect.php file)
if (isset($_GET['color']) && isset($_GET['altmode']))
{
$stmt = $conn->prepare("SELECT id,name,image1 FROM transformers WHERE color=:color AND altmode=:altmode");
$stmt->bindParam(':color', $_GET['color']);
$stmt->bindParam(':altmode',$_GET['altmode']);
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
echo "this works";
/*
foreach ($variable as $key => $value) {
and here i am lost
}
*/
} else
{
echo "<p id=\"error\">You didn't search for anything! Go to the main page to find a figure!</p>";
}
(edited the code because what I had included was just completely wrong, but still it shows no signs of being right)
this code should, if Altmode and Color are set via the Get method, execute the query, not write it out anywhere but instead output "this works". Then I commented out some code that would be a start of a function writing out the table. However there is something wrong even with the query which i can't see because it doesn't say "this works"
But my main problem is still how to continue on from that.
Function render makes website 500% slow! Can anyone fix that please ?
Someone told me :
because it sends a database request on each iteration of the loop (it's not the only problem with this chunk of code but it's the most taxing one)
Yes I understand what that means. His way is:
you need to get all of the data before you start building the menu,
then you just insert the data instead of requesting more data on each
iteration
But i don't know how i must do it!
<?php
$menu_html='';
function render_menu($parent_id,$actmenuid)
{
$obj = new Database();
$con = $obj->dbconnectt();
global $menu_html;
$result=mysqli_query($con, "select * from tbl_menu where parent_id='$parent_id'");
if(mysqli_num_rows($result)==0) return;
if($parent_id==0){
$menu_html.='<ul class="topnav">';
}else{
$menu_html.='<ul>';
}
while($row=mysqli_fetch_array($result)) {
$childnum = $obj->recordcount("SELECT * FROM tbl_menu WHERE parent_id='".$row['id']."'");
if($childnum == 0){
$linkvalue='/category/'.$row['id'].'.html';
} else{
$linkvalue='#';
}
if($row['id']==$actmenuid && $actmenuid !=NULL){
$actv='class="active"';
}else{
$actv='';
}
$menu_html.='<li '.$actv.'>'.$row['title'].'';
render_menu($row['id'],$actmenuid);
$menu_html.='</li>';
}
$menu_html.='</ul>';return $menu_html;
}
if($isDsh==false){
echo render_menu(0,$actmenuid);
}
?>
Depending on how many records you have, try removing this query from inside the loop since it's running for every record on the first query.
$childnum = $obj->recordcount("SELECT * FROM tbl_menu WHERE parent_id='".$row['id']."'");
Change it a single query like this where it returns counts for each parent idea, and place it outside of the loop:
$parentcount = mysqli_query($con, ("SELECT parent_id, count(*) FROM tbl_menu GROUP BY parent_id");
There may be other issues, so please post the database structure and number of records that you're working with too.
Don't make recursive queries.
Having "more than 1000" rows is not too big. You can simply call everything from the table into php, then perform the recursive html build in php this will have a memory overhead, but far less processing overhead because you only ever make one trip to the db.
Alternatively (when your db table is prohibitively large), you should avoid gathering rows unnecessarily by adding a new column. The new column will store all "descendants" for the respective row when the row is INSERTed or update it when it is UPDATEd. Then you only need to reference this column when needing to call specific rows. In other words, do the recursive processing only once (when writing to the db) AND not when needing to display the data. This will, again, produce a finite result set in one query which can then be recursively traversed to build the desired output.
basically you need to do what #spudly has suggested.
But there is a small catch in his solution which depending on the number of the rows in yous tbl_menu table you may use a big chunk of memory to fetch all the records.
you can optimise it more with using his solution but changing the query to:
select
parent_tbl_menu.id,
count(child_tbl_menu.id) as cnt
from
tbl_menu as parent_tbl_menu
left join
tbl_menu as child_tbl_menu
on parent_tbl_menu.id = child_tbl_menu.parent_id
where
parent_tbl_menu.parent_id = ?
group by
parent_tbl_menu.id
This way you will only fetch the child records of a specific parent.
And please consider using prepared statements as your code has sql injection vulnerability.
Connect (from PHP to MySQL) only once for the entire web page.
Don't put a SELECT inside a loop if you can do all the work in a single SELECT, such as with a JOIN. (Exception: A "hierarchical" table needs the nested SELECT. Exception to the exception: MySQL 8.0 and MariaDB 10.2 can do it with a "recursive CTE".)
Don't fetch all the columns (SELECT *) when all you want it is a recordcount. Instead, SELECT COUNT(*) ... and use the number returned.
1000 of anything is probably excessive for a web page. Re-think the UI.
I have two mysql tables. I want to get the data from these tables and show it in a loop. The data is totally unrelated to each other and should stay that way. I just need to show data from these two different tables in the same place.
I tried the mysqli_multi_query, but I couldn't show the results from an individual column like I can with a normal query.
For each of these two tables, I need 2 SELECT statements with two WHERE clauses. Does anyone know how to do this?
I've tried all different ways of trying to get the info from both tables and just show them in one loop. I've tried mysqli_multi_query, but don't know how to save specific column results in a variable.
$sql = "SELECT *
FROM misc
WHERE height LIKE '$height_input'
SELECT *
FROM bolts
WHERE name LIKE '$bolt_name_input'
;
";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$height_row = $row['height'];
$bolt_name_input = $row['name'];
?>
Height Row: <?php echo $height_row; ?>m<br />
bolt Name: <?php echo $bolt_name_input; ?><br />
} //while
My error message is generally "Trying to get property 'num_rows' of non-object".
Yes everyone, I have taught myself PHP and MySQL through online tutorials and have not had a lot of experience with them yet. I apologise, I am still getting the hang of this.
I have just worked out now by trial and error that I can show information from a table outside of the while loop. I had no idea I could do this! Which changes everything. So I can select information from various database tables using different SELECT statements and then echo them all into one place in my HTML table underneath it on my web page. The results don't have to be shown in the while loop, they can be outside it.
So my structure now looks like this basically:
SELECT from table 1 column 1 WHERE (form input value)
num rows
while loop
$height = $row_height['height'];
end num rows
end while loop
SELECT from table 2 column 1 WHERE (form input value)
num rows
while loop
$bolts = $row_bolts['bolts'];
end num rows
end while loop
<table>
<tr>
<td>echo $height</td>
<td>echo $bolts</td>
</tr>
</table>
So, this is working for me to retrieve multiple results from my different tables. I have to change the variable names of the sql statement each time, I guess I could do it with a function so i can repeat it and make it look neater, but this is working for me this way. So, with bolts I am using the variable names $sql_bolts, $result_bolts and $row_bolts and with height I am using variable names $sql_height, $result_height and $row_height and so on.
$bolts_input = $_POST['bolts'];
$sql_bolts = "
SELECT *
FROM bolts
WHERE name LIKE '$bolts_input'
;";
$result_bolts = $conn->query($sql_bolts);
if ($result_bolts->num_rows > 0) {
// output data of each row
while($row_bolts = $result_bolts->fetch_assoc()) {
$bolts = $row_bolts['name'];
} //bolts while
} // bolts num rows
I am not using mysql, but mysqli. I did a whole bunch of tutorials on PDO and how to connect to the database and retrieve information and just couldn't figure out how to show values from a row like I can with the above. It's frustrating because I want to use the latest methods, but I can't find how to online that makes sense to me.
Thank you for eveyone's comments so far.
I want it to echo how many posts there are in bestallt where its ID is 1 from the table order and display it as how many posts there are in numbers. I am connected to the database in the PHP file, that's not an issue. I'm just not sure how to put it all down in PHP, quite new to this. I just can't get it to echo what I want, nothing comes out/I get an error.
Any help is appreciated!
Your present code does not fetch the data from the database, it simply echoes the SQL query you have written.
Quite a lot more code goes in to fetching results from a mysql database, and I am not sure reproducing a full explanation here will serve anyone's interests. However, you may wish to view the examples of how to use PDO (a method of using mysql databases from php) here, and then either edit or re-ask your question if you find you have specific difficulties following those examples.
Try this code:
<td>
<?php
$sql = "SELECT count(*) FROM order WHERE bestallt='1'"; // Your SQL query
$response = mysql_query($sql);
if (mysql_num_rows($response) == 0) {
// Your query returned 0 rows!
}
while($row = mysql_fetch_array($response)){
// For each row returned from your query
// $row is an array
// For example, You can use it:
echo $row['data1'];
echo $row['data2'];
echo $row['data3'];
// data1, data2, data3 are the name of the fiels in your database
}
?>
</td>
Have a nice day!
Try this,
$sql = "SELECT count(*) FROM order WHERE bestallt='1'"
$res=mysql_query($sql);
$arr=mysql_fetch_array($res);
echo "<pre>";print_r($arr); //you will get whole array for matching record of your order table if found anything
To learn more, you can check my earlier Answer: how generate report between the two dates using datepicker,ajax,php,mysql.?
In that answer I have described whole working demo.
My first post, tried to be as thorough as possible, apologies in advance if I've gotten something wrong. I'm pretty novice with PHP/SQL as well so please be patient with me. I've found a couple of similar questions about loops within loops but I'm not sure the solutions apply in my case.
I have two tables, tws_workshopNames and tws_workshops. The primary key from tws_workshopNames is used as a foreign key in tws_workshops to relate the two tables. The reason I've split this into two tables is there are many cases where the same workshop name/price/description is offered on multiple dates/times.
Can't submit a screenshot but here's a simplified outline of the table design in SQL Server:
tws_workshopNames:
workshopNameID (pri)
description
price
etc.
tws_workshops:
workshopID (pri)
workshopNameID (foreign)
date
time
etc.
What I want to happen is basically this:
query tws_workshopNames table and display workshopName/price/description/etc.
for each workshopName go through the tws_workshops table and display all records that have the same workshopNameID
In other words, go through tws_workshopNames and display the first workshopName, then go through tws_workshops and display all records that are related to that workshopName, then go to next workshopName in tws_workshopNames, display all records related to that workshopName etc.
I'm able to achieve the desired result by using a while loop within a while loop wherein the outer loop does a call to tws_workshopNames and the nested loop does a call to the tws_workshops table. However I've been reading a lot about this and it's clear this is not a good approach as it results in a lot of calls to the db, but I'm having a hard time understanding any alternatives.
Desired output:
Workshop 1
price
description
date (of workshop 1)
time (of workshop 1)
...
Workshop 2
price
description
first date (of workshop 2)
first time (of workshop 2)
second date (of workshop 2)
second time (of workshop 2)
third date (of workshop 2)
third time (of workshop 2)
...
Workshop 3
price
description
date (of workshop 3)
time (of workshop 3)
...
etc.
Here is the current code that works with nested while loops:
<?php
// query workshopNames table, what types of workshops are available?
$query = mssql_init("tws_sp_workshopNames", $g_dbc);
// pull up result
$result = mssql_execute($query);
$numRows = mssql_num_rows($result);
while($row = mssql_fetch_array($result)) {
echo "<div style=\"...\">
<span class=\"sectionHeader\">" . $row['workshopName'] . "</span><br />
<span class=\"bodyText\"><strong>" . $row['price'] . "</strong></span><br />
<span class=\"bodyText\">" . $row['description'] . "</span>";
$workshopNameID = $row['workshopNameID'];
// query workshops table, what are the dates/times for each individual workshop?
$query2 = mssql_init("tws_sp_workshops", $g_dbc);
mssql_bind($query2, "#workshopNameID", $workshopNameID, SQLVARCHAR);
//pull up result
$result2 = mssql_execute($query2);
$numRows2 = mssql_num_rows($result2);
while($row2 = mssql_fetch_array($result2)) {
echo $row2[date] . " ";
echo $row2[time] . "<br />";
};
echo "</div><br />";
};
?>
The stored procedures are very simple:
tws_sp_workshopNames = "SELECT workshopNameID, workshopName, description, location, price FROM tws_workshopNames"
tws_sp_workshops = "SELECT date, time, maxTeachers, maxStudents, teachersEnrolled, studentsEnrolled FROM tws_workshops WHERE workshopNameID=#workshopNameID"
Hope that's all relatively clear, all I'm really looking for is a better way to get the same result, i.e. a solution that does not involve a db call within the loops.
Thanks in advance for any help, been a few days straight banging my head against this one...
You are correct to avoid usage of looping queries in this case (since the desired result can be achieved with just a simple JOIN in one query).
I would avoid using GROUP_CONCAT() as well because there is a character limit (by default, you can change it), plus you have to parse the data it outputs, which is kind of a pain. I would just get all the data you need by joining and get every row. Then load the data into arrays using the workshop ID as the key but leave the array open to append each of your time data as a new array:
$workshops[$workshop_name][] = $timesArray;
Then on your output you can loop, but you don't have to hit the database on each call:
foreach ($workshops as $workshop_name => $times)
{
echo $workshop_name;
foreach ($times as $time)
{
echo $time;
}
echo "<br>";
}
This is not the exact code, and as you've pointed out in your question, you want to keep/display some other information about the workshops - just play around with the array structure until you get all the data you need in a hierarchy. You can use something like http://kevin.vanzonneveld.net/techblog/article/convert_anything_to_tree_structures_in_php/ if you are trying to build a deep tree structure, but I think that's overkill for this example.
Since this is what I would call an "Intermediate Level" question, I think you should try to work through it (THIS is what makes you a good programmer, not copy/paste) using my suggestions. If you get stuck, comment and I'll help you further.
I don't see anything wrong with the way you're doing things. I suppose you could concatenate the result and then manipulate the output in your application using one query. Your query might looks something like
SELECT
n.workshopNameId,
n.price,
n.description,
GROUP_CONCAT(w.date) as dates,
GROUP_CONCAT(w.time) as times
FROM tws_workshopNames n
INNER JOIN tws_workshops w USING(workshopNameID)
GROUP BY n.workshopNameID