I am creating an in-house patient calendar, the clinic has more than 40K patients in the database.
I am trying to list around 9000 rows but it is taking extremely long time, I tried with 100 rows, it takes around 20 second, how can I make it much faster?
Here is my code:
$getPatients = $db->query("set names 'utf8'");
$q = "SELECT id, p_type, clinic_id, recommended_doctor, hdyhau, partnership_companies, p_auto_control_date, first_name, last_name, company, mobile, p_city, p_state, p_country, saved_by FROM dg_patients_patients WHERE clinic_id = {$defaultClinic} ORDER BY first_name ASC LIMIT 100";
$getPatients = $db->query($q);
$patientList = "";
while ($row = mysql_fetch_array($getPatients)) {
//Get Patient Type
$getPatientType = $db->query("set names 'utf8'");
$q = "SELECT * FROM dg_patient_type WHERE id = {$row['p_type']}";
$getPatientType = $db->query($q);
$patientType = mysql_fetch_array($getPatientType);
//Get Partnership Company
if($row['partnership_companies'] != '' && $row['partnership_companies'] > 0) {
$getPC = $db->query("set names 'utf8'");
$q = "SELECT * FROM dg_partnership_companies WHERE id = {$row['partnership_companies']}";
$getPC = $db->query($q);
$pc = mysql_fetch_array($getPC);
$pcname = $pc['pc_name'];
} else {
$pcname = '';
}
if(!empty($row['saved_by'])){
//Get User
$getUser = $db->query("set names 'utf8'");
$q = "SELECT * FROM dg_users WHERE id = {$row['saved_by']}";
$getUser = $db->query($q);
$user = mysql_fetch_array($getUser);
$savedby = $user['first_name'];
} else {
$savedby = '';
}
//Get Total Appointments
$q1 = "SELECT * FROM dg_appointments WHERE (appointment_type = 1 OR appointment_type =2 ) AND patient_id = {$row['id']}";
$getApps = $db->query($q1);
$totalAppointments = mysql_num_rows($getApps);
//Get Latest Appointment Date
$q11 = "SELECT * FROM dg_appointments WHERE appointment_status = 4 AND patient_id = {$row['id']} ORDER BY start_date DESC, start_time DESC LIMIT 1";
$getLastesApp = $db->query($q11);
$lastesApp = mysql_fetch_array($getLastesApp);
//Get Clinic
$getClinic = $db->query("set names 'utf8'");
$q = "SELECT * FROM dg_clinics WHERE id = {$row['clinic_id']}";
$getClinic = $db->query($q);
$clinic = mysql_fetch_array($getClinic);
//Get Doctor
if($row['recommended_doctor'] != '' && $row['recommended_doctor'] > 0) {
$getDoctor = $db->query("set names 'utf8'");
$q = "SELECT * FROM dg_users WHERE department = 2 AND id = {$row['recommended_doctor']}";
$getDoctor = $db->query($q);
$doctor = mysql_fetch_array($getDoctor);
$doctorID = $doctor['first_name'].' '.$doctor['last_name'];
} else {
$doctorID = '-';
}
//Get HDYHAU
if($row['hdyhau'] != '' && $row['hdyhau'] > 0){
$q = "SELECT * FROM dg_hdyhau WHERE id = {$row['hdyhau']}";
$getHDYHAU = $db->query($q);
$HDYHAU = mysql_fetch_array($getHDYHAU);
$HDYHAUID = $HDYHAU['hdyhau_name'];
} else {
$HDYHAUID = '-';
}
//Get Country
if($row['p_country'] != '' && $row['p_country'] > 0){
$getCountry = $db->query("set names 'utf8'");
$sql = "SELECT * FROM dg_ulke WHERE Id = {$row['p_country']}";
$getCountry = $db->query($sql);
$country = mysql_fetch_array($getCountry);
$countryID = $country['tr_TR'];
} else {
$countryID = '-';
}
//Get Cities
if($row['p_state'] != '' && $row['p_state'] > 0){
$getState = $db->query("set names 'utf8'");
$sql = "SELECT * FROM dg_il WHERE Id = {$row['p_state']}";
$getState = $db->query($sql);
$state = mysql_fetch_array($getState);
$stateID = $state['IlAdi'];
} else {
$stateID = '-';
}
//Get Streets
if($row['p_city'] != '' && $row['p_city'] > 0){
$getCity = $db->query("set names 'utf8'");
$sql = "SELECT * FROM dg_ilce WHERE Id = {$row['p_city']}";
$getCity = $db->query($sql);
$city = mysql_fetch_array($getCity);
$cityID = $city['IlceAdi'];
} else {
$cityID = '-';
}
$btn1 = "<a href='/apps/patients/patient-file.php?patientid=".$row['id']."#treatment_finance' target='_blank'><img src='/assets/images/Letter-T-blue-icon.png' width='24' height='24'></a>";
$btn2 = "<a href='/apps/patients/patient-file.php?patientid=".$row['id']."#patient_information' target='_blank'>".$row['first_name']." ".$row['last_name']."</a>";
if($lastesApp['start_date']){
$latestAppDate = date('d.m.Y', strtotime($lastesApp['start_date']));
} else {
$latestAppDate = '-';
}
if($row['p_auto_control_date'] != '' && $row['p_auto_control_date'] != '0000-00-00'){
$pacd = date('d.m.Y', strtotime($row['p_auto_control_date']));
} else {
$pacd = '-';
}
$btn5 = "<div class='checkbox checkbox-primary'><input id='checkboxPatients".$row['id']."' class='styled checkAllPatients' type='checkbox' name='checkAllPatients[]' value='".$row['id']."'><label for='checkboxPatients".$row['id']."'></label></div>";
$patientList .= "<tr>";
$patientList .= "<td>".$btn5."</td>";
$patientList .= "<td>".$clinic['clinic_name']."</td>";
$patientList .= "<td>".$btn1."</td>";
$patientList .= "<td>".$btn2."</td>";
$patientList .= "<td>".$row['mobile']."</td>";
$patientList .= "<td>".$cityID."</td>";
$patientList .= "<td>".$stateID."</td>";
$patientList .= "<td>".$row['company']."</td>";
$patientList .= "<td>".$pcname."</td>";
$patientList .= "<td>".$totalAppointments."</td>";
$patientList .= "<td>".$latestAppDate."</td>";
$patientList .= "<td>".$pacd."</td>";
$patientList .= "<td>".$savedby."</td>";
$patientList .= "<td>".$doctorID."</td>";
$patientList .= "<td>".$HDYHAUID."</td>";
$patientList .= "<td>".$countryID."</td>";
$patientList .= "</tr>";
}
echo $patientList;
You need to make index to clinic_id and first_name.
See this document http://www.w3schools.com/sql/sql_create_index.asp will help
You using too many queries in this code. reduce query will make better. use join to joining multiple table information to once, with conditions. http://www.w3schools.com/sql/sql_join_left.asp
set names utf8 only need once per code. If problem to fetching other language, checking my.cnf first to define default character set with server and connection.
use indexing in your table, index those fields which are using in where clause.
instead of use select * specify column name
instead of interacting database multiple type,fetch data from database at a time then using php show the data.
Try not using SELECT *.... instead give names of column(s) that you require and create Index on those column(s).
Warning: Just because indexing helps don't create index on all the columns cause index uses extra space
Check how to give indexing. I have attached image for you.
Syntax
ALTER TABLE `Table_name` ADD INDEX ( `Column_name` ) ;
Following are my suggestions:
1) You have 11 select queries. Out of it, 10 are in the loop and at least half of them run in the loop.
2) It means for every records in the top query, you are running 6 queries. For 100 rows, it is 600 queries (600 times database interaction). Therefore, your page is taking 20 seconds at least.
3) Again, every SQL has SELECT *, this takes more time as database tables may have number of fields.
Solution
1) Every SQL has SELECT *, use only required fields.
2) Try not to fire query in the loop.
3) Instead, get all records before loop and access them by key value array.
4) For example, the sql:
$q = "SELECT * FROM dg_users WHERE id = {$row['saved_by']}";
You can have an array of all users in array with key as user id and value as user name
And in the loop, get the value from this array like:
$savedby = isset($users[$row['saved_by']]) ? $users[$row['saved_by']] : '';
Repeat the same for all queries in the loop.
Hope, it will help you.
Related
Out of two search selections if a visitor select one only there is no search result. Following is my sql query:
$sql = "SELECT * FROM table WHERE column1='$column1' AND column2 ='$column2' ORDER BY id DESC
If I use 'OR' or otherwise I got wrong result in pagination. What should be right coding if a visitor opted only one criteria to search he will get result in first and subsequent pages?
In PHP construct your query:
$where = [];
$params = [];
if (!empty($column1)) {
$where[] = 'column1 = :column1';
$params[':column1'] = $column1;
} else {
$where[] = 'column1 IS NULL';
}
if (!empty($column2)) {
$where[] = 'column2 = :column2';
$params[':column2'] = $column2;
} else {
$where[] = 'column2 IS NULL';
}
if (!empty($where)) {
$pdo
->prepare("SELECT * FROM table WHERE ".implode(' AND ', $where))
->execute($params);
}
If you allow selection only by one column, remove else parts
A fast solution is that you can put the filters into a variable checking if the values of $column1 or $column2 it's filled and add after that in the SELECT clause:
$where_column = 'WHERE ';
if ($column1 != false)
$where_column .= "column1='$column1'";
if ($column2 != false) {
if ($where_column != 'WHERE') {
$where_column .= "AND column2='$column2'";
else
$where_column = "column2='$column2'";
}
}
$sql = "SELECT * FROM table $where_column ORDER BY id DESC
I have the following code
$sql = "SET #uid := (SELECT ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);";
$sql = "UPDATE channels SET Used = 1 WHERE ID = #uid;";
$sql = "SELECT * FROM channels WHERE ID IN = #uid;";
$result = mysqli_multi_query($conn, $sql)
or die( mysqli_error($sql) );
if (mysqli_num_rows($result) > 0) {
$text = '';
while($row = mysqli_fetch_assoc($result)) {
$Channel_Location = $row['Channel_Location'];
$text = $text . $Channel_Location;
}
}
Now the issue i'm having is the php isnt displaying the result returned by the MYSQL query which is stored in a session later on in the code to be displayed on a dummy page it comes up with the following error
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result
The my SQL query does exactly what I need it to I just need to, so I don't really want to change it. I just need some advice on how i'd get the PHP to echo the #uid
is there anyone willing to help me solve the issue? if so thankyou.
You have 3 queries in your $sql so you should use multi_query function
http://php.net/manual/en/mysqli.multi-query.php
And you can change your first query to:
SET #uid = 0;
SELECT #uid := ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);
Update You can try this fragment of your code modified with all commented improvements.
$sql = 'SET #uid = 0;';
$sql .= 'SELECT #uid:= ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);';
$sql .= 'UPDATE channels SET Used = 1 WHERE ID = #uid;';
$sql .= 'SELECT * FROM channels WHERE ID IN = #uid;';
if (mysqli_multi_query($conn, $sql)) {
do {
$result = mysqli_store_result($conn);
} while(mysqli_next_result($conn));
if (mysqli_num_rows($result) > 0) {
$text = '';
while($row = mysqli_fetch_assoc($result)) {
$Channel_Location = $row['Channel_Location'];
$text = $text . $Channel_Location;
}
}
} else {
die( mysqli_error($conn) );
}
I'm trying to optimize this check I have. I need to check table called lines and see if any row has matching Earned and Maxearned values (only rows with Position 1,2,3,4). If they do, I need to grab Earned from that row, write it in a different table called bank and remove that row from table called lines. This is what I have:
$sql3 = "SELECT * FROM `lines` WHERE Position <= 4 AND Linenum = '$linenum' AND Earned = Maxearned";
$result3 = mysql_query($sql3);
if (mysql_num_rows($result3) != 0)
{
while ($row3 = mysql_fetch_array($result3))
{
$users[] = $row3['User'];
}
foreach ($users as $user)
{
$sql6 = "SELECT * FROM `lines` WHERE Position <= 4 AND Linenum = '$linenum' AND Earned = Maxearned AND User = '$user'";
$result4 = mysql_query($sql6);
while ($row4 = mysql_fetch_array($result4))
{
$earned = $row4['Earned'];
}
$today = date("Y-m-d");
$method = "Queue money";
$type = "Earned";
$status = "Completed";
$sql4 = "INSERT INTO bank (User,Amount,Method,Transdate,Type,Status) VALUES ('$user','$earned','$method','$today','$type','$status')";
$sql5 = "DELETE FROM `lines` WHERE Position <= 4 AND Linenum = '$linenum' AND Earned = Maxearned AND User = '$user'";
}
$sql7 = "UPDATE `lines` SET Position = Position - 1 WHERE Linenum = '$linenum'";
}
I'm trying to avoid having to run a different query ($sql6 and the while after that) to grab the value of Earned column. Is there a way to do this? I've tried everything and this is pretty much the best I came up with.
You can do something like this:
mysql_query("SET AUTOCOMMIT=0");
mysql_query("START TRANSACTION");
$sql3 = "SELECT * FROM `lines` WHERE Position <= 4 AND Linenum = '$linenum' AND Earned = Maxearned";
$result3 = mysql_query($sql3);
if (mysql_num_rows($result3) != 0)
{
while ($row3 = mysql_fetch_array($result3))
{
$users[] = $row3['User'];
}
$users_to_compare = "(" . rtrim(implode(",", $users),',') . ")";
$sql4 = "SELECT * FROM `lines` WHERE Position <= 4 AND Linenum = '$linenum' AND Earned = Maxearned AND User IN $users_to_compare";
$result4 = mysql_query($sql4);
while ($row4 = mysql_fetch_array($result4))
{
$earned = $row4['Earned'];
$today = date("Y-m-d");
$method = "Queue money";
$type = "Earned";
$status = "Completed";
$sql5 = "INSERT INTO bank (User,Amount,Method,Transdate,Type,Status) VALUES ('{$row4['User']}','$earned','$method','$today','$type','$status')";
$result5 = mysql_query($sql5);
}
$sql6 = "DELETE FROM `lines` WHERE Position <= 4 AND Linenum = '$linenum' AND Earned = Maxearned AND User IN $users_to_compare";
$result6 = mysql_query($sql6);
$sql7 = "UPDATE `lines` SET Position = Position - 1 WHERE Linenum = '$linenum'";
$result7 = mysql_query($sql7);
if ($result5 && $result5 && $result7) {
mysql_query("COMMIT");
} else {
mysql_query("ROLLBACK");
}
}
Going one step further you can also use Batch INSERT for you insert queries
Note: Dont forget that mysql_* versions are depreceated you should use mysqli_*
I was wondering if there was an easy way to do this:
I have a user_id column and then 33 other columns with either a '0' or a '1' as the type. How can I easily select all of the columns where the user_id = 320 and the column's data equals 1?
The column titles are labeled 1-33. In the end I want to join it to another table where 1-33 is the id to a label column.
Does this make sense?
Thanks for any help!
Try this I get all the fields and test if it BIT and then inject it to the query
And please tell me the result
<?php
$result = mysql_query("SHOW COLUMNS FROM sometable");
if (!$result){
echo 'Could not run query: ' . mysql_error();
exit;
}
if (mysql_num_rows($result) > 0){
$str ="";
$nums = mysql_num_rows($result);
$i = 0 ;
while ($row = mysql_fetch_assoc($result)){
$i++;
if($row['Type'] = 'BIT' && $i != $nums){
$str .= " WHERE `".$row['Field']."` = 1 AND";
}
elseif($row['Type'] = 'BIT' && $i == $nums){
$str .= " WHERE `".$row['Field']."` = 1 ";
}
}
}
$query = "SELECT * FROM mytable user_id = 320 AND ".$str;
$q = mysql_query($query);
This is for the first part of you question
the second part the same operation
and this working without knowing the fields name
I have a table with 12 columns and 200 rows. I want to efficiently check for fields that are empty/null in this table using php/mysql. eg. "(col 3 row 30) is empty". Is there a function that can do that?
In brief: SELECT * FROM TABLE_PRODUCTS WHERE ANY COLUMN HAS EMPTY FIELDS.
empty != null
select * from table_products where column is null or column='';
SELECT * FROM table WHERE COLUMN IS NULL
As far as I know there's no function to check every column in MySQL, I guess you'll have to loop through the columns something like this...
$columns = array('column1','column2','column3');
foreach($columns as $column){
$where .= "$column = '' AND ";
}
$where = substr($where, 0, -4);
$result = mysql_query("SELECT * FROM table WHERE $where",$database_connection);
//do something with $result;
The = '' will get the empty fields for you.
you could always try this approach:
//do connection stuff beforehand
$tableName = "foo";
$q1 = <<<SQL
SELECT
CONCAT(
"SELECT * FROM $tableName WHERE" ,
GROUP_CONCAT(
'(' ,
'`' ,
column_name,
'`' ,
' is NULL OR ',
'`' ,
column_name ,
'`',
' = ""' , ')'
SEPARATOR ' OR ')
) AS foo
FROM
information_schema.columns
WHERE
table_name = "$tableName"
SQL;
$rows = mysql_query($q1);
if ($rows)
{
$row = mysql_fetch_array($rows);
$q2 = $row[0];
}
$null_blank_rows = mysql_query($q2);
// process the null / blank rows..
<?php
set_time_limit(1000);
$schematable = "schema.table";
$desc = mysql_query('describe '.$schematable) or die(mysql_error());
while ($row = mysql_fetch_array($desc)){
$field = $row['Field'];
$result = mysql_query('select * from '.$schematable.' where `'.$field.'` is not null or `'.$field.'` != ""');
if (mysql_num_rows($result) == 0){
echo $field.' has no data <br/>';
}
}
?>
$sql = "SELECT * FROM TABLE_PRODUCTS";
$res = mysql_query($sql);
$emptyFields = array();
while ($row = mysql_fetch_array($res)) {
foreach($row as $key => $field) {
if(empty($field)) || is_null($field) {
$emptyFields[] = sprintf('Field "%s" on entry "%d" is empty/null', $key, $row['table_primary_key']);
}
}
}
print_r($emptyFields);
Not tested so it might have typos but that's the main idea.
That's if you want to know exactly which column is empty or NULL.
Also it's not a very effective way to do it on a very big table, but should be fast with a 200 row long table. Perhaps there are neater solutions for handling your empty/null fields in your application that don't involve having to explicitly detect them like that but that depends on what you want to do :)
Check this code for empty field
$sql = "SELECT * FROM tablename WHERE condition";
$res = mysql_query($sql);
while ($row = mysql_fetch_assoc($res)) {
foreach($row as $key => $field) {
echo "<br>";
if(empty($row[$key])){
echo $key." : empty field :"."<br>";
}else{
echo $key." =" . $field."<br>"; 1
}
}
}
Here i'm using a table with name words
$show_lang = $db_conx -> query("SHOW COLUMNS FROM words");
while ($col = $show_lang -> fetch_assoc()) {
$field = $col['Field'];
$sel_lan = $db_conx -> query("SELECT * FROM words WHERE $field = '' ");
$word_count = mysqli_num_rows($sel_lan);
echo "the field ".$field." is empty at:";
if ($word_count != 0) {
while($fetch = $sel_lan -> fetch_array()){
echo "<br>id = ".$fetch['id']; //hope you have the field id...
}
}
}
There is no function like that but if other languages are allowed, you can extract the structure of a table and use that to generate the query.
If you only need this for a single table with 30 columns, it would be faster to write the query by hand...