My business has a simple invoicing system written by me a few years ago in php with a MySQL database. When I wrote it, I knew just enough to be dangerous. While it does work, a lot of the code is very inefficient, slow and poorly conceived, so I'm re-writing some of it in the hopes of fixing it.
There are two tables: customers and transactions. When invoices need to be created, there are two queries, the second unfortunately in a while loop. Here is some simplified pseudo-code to show what I'm doing:
// Get list of customers who owe something
SELECT name, address
FROM customers
WHERE
(SELECT COUNT(*) FROM transactions
WHERE transactions.customer_id = customers.id
AND owed > 0)
> 0
ORDER BY address
//loop through that result and query the transactions table to get a
//list of charges for each customer. Like:
while ($row = customer_array()) {
echo name_and_address;
SELECT * FROM transactions WHERE id = $row['customer_id']
AND owed = TRUE ORDER BY date
while ($row = transactions_array()) {
echo each_transaction_row;
}
So obviously the nested loops, subqueries and queries in loops are bad, worse and slow. I've tried joins but can't seem to figure out how to make them work correctly in this context. What is the correct way to do something like this? Can it be done with a single query?
Table structure:
CREATE TABLE `customer_data` (
`account_id` int(6) NOT NULL AUTO_INCREMENT,
`service_address` varchar(255) DEFAULT NULL,
`service_zipcode` int(5) DEFAULT NULL,
`first_name` varchar(255) DEFAULT NULL,
`last_name` varchar(255) DEFAULT NULL,
`billing_address1` varchar(255) DEFAULT NULL,
`billing_address2` varchar(255) DEFAULT NULL,
`billing_city` varchar(255) DEFAULT NULL,
`billing_state` varchar(2) DEFAULT NULL,
`billing_zipcode` varchar(20) DEFAULT NULL,
`phone1` varchar(100) DEFAULT NULL,
`phone2` varchar(100) DEFAULT NULL,
`quoted_price` int(6) DEFAULT NULL,
`current_price` int(6) DEFAULT NULL,
`original_interval` varchar(10) DEFAULT NULL,
`current_interval` varchar(7) DEFAULT NULL,
`temp_interval` int(5) NOT NULL,
`email` varchar(100) DEFAULT NULL,
`origin_date` varchar(20) DEFAULT NULL,
`remarks` text,
`crew_remarks` text NOT NULL,
`customer_type` varchar(10) DEFAULT NULL,
`perm_crew_assign` int(5) NOT NULL DEFAULT '0',
`temp_crew_assign` int(5) NOT NULL,
`date_last_service` date DEFAULT NULL,
`next_scheduled_date` date DEFAULT NULL,
`excluded_days` varchar(255) NOT NULL,
`special_instructions` text NOT NULL,
`inactive` tinyint(1) NOT NULL DEFAULT '0',
`location` varchar(255) NOT NULL,
`sent_letter` date NOT NULL,
`date_added` datetime NOT NULL,
`email_notify` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`account_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1687 DEFAULT CHARSET=utf8
CREATE TABLE `transactions` (
`transaction_id` int(10) NOT NULL AUTO_INCREMENT,
`account_id` int(6) NOT NULL,
`crew_id` int(3) NOT NULL,
`date_performed` date NOT NULL,
`date_recorded` datetime NOT NULL,
`price` int(6) NOT NULL,
`amount_paid` int(6) NOT NULL,
`description` varchar(255) NOT NULL,
`user` varchar(255) NOT NULL,
`status` int(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`transaction_id`)
) ENGINE=InnoDB AUTO_INCREMENT=69233 DEFAULT CHARSET=latin1
You can do this with one query and one loop. You can join the two tables and sort the result. Then when the name changes, you know you are starting a new customer.
SELECT c.name, c.address, t.*
FROM customers AS c
JOIN transactions AS t ON (t.customer_id = c.customers.id)
WHERE c.owed > 0
ORDER BY `c`.`name`
// Data looks like this
// | customer.name | customer.address | transaction.* |
$prevName = null;
$prevCustTransList = [];
$prevCustTransTotalOwed = 0;
while ($row = result_array()) { // pseudo code
if ( $row['c.name'] != $prevName ) {
if ( $prevName != null && $prevCustTransTotalOwed > 0 ) {
echo $prevName; // pseudo code
foreach($prevCustTransList as $t) {
echo $t; // pseudo code
}
}
$prevName = $row['c.name'];
$prevCustTransTotalOwed = 0;
$prevCustTransList = [];
}
// Keep the list of transactions to print out later.
$prevCustTransList[] = transaction data; // pseudo code
// Keep a running total of the amount owed
// Replace with actual calculation
$prevCustTransTotalOwed += transaction.price;
}
Yes you can do this in one query, ordering by account_id. In your 'transactions' table account_id should be indexed, since you'll be using it to join to 'customer_data'.
$st_date = '2016-01-01';
$end_date = '2016-02-01';
//select sql
SELECT c.name,c.account_id, ts.*
FROM customer_data c
INNER JOIN transactions ts ON (c.account_id = ts.account_id)
WHERE ts.price > 0 and ts.date_performed between $st_date and $end_data
$current_account_id = null;
while ($row = $results) {
if ($current_account_id != $row['account_id']) {
//print customer name, details, etc..
}
//print the transactions detail
echo $results['transaction_id']; //etc...
//keep track of the current customer
$current_account_id = $row['account_id']
}
Related
I use Codeigniter 3.1.11 and have some code which makes one big query to MySQL with an array. The time of a query with a limit of 30000 is about 9 seconds.
How can I reduce the request time? Maybe by using some indexes on my table, or do you know another method? If I need to use indexes, what indexes would I need to use and how can I use these indexes in my query on Codeigniter?
Code from model:
function rows_update() {
$query = $this->db->order_by('rating', 'DESC')->get_where('members', 'game_rating_and_balance_update_last_time <= now() - INTERVAL 1 DAY', '30000', '0');
$arrUpdateBatchData = [];
while ($row = $query->unbuffered_row('array'))
{
// some code here
$arrUpdateData = [
'UserID' => $row['UserID'],
'game_vault_balance' => $new_game_vault_balance,
'game_available_balance' => $new_game_available_balance,
'rating' => $rating_member,
'game_rating_and_balance_update_last_time' => date('Y-m-d H:i:s')
];
$arrUpdateBatchData[] = $arrUpdateData;
if (count($arrUpdateBatchData) > 500)
{
$this->db->update_batch('members', $arrUpdateBatchData, 'UserID');
$arrUpdateBatchData = [];
}
}
//update last items
if (count($arrUpdateBatchData) > 0)
{
$this->db->update_batch('members', $arrUpdateBatchData, 'UserID');
$arrUpdateBatchData = [];
}
return;
}
Raw query to MySQL with update_batch (I simply write only one row from an array):
UPDATE members SET game_vault_balance = CASE WHEN UserID = '9915075' THEN 803.60516004772 ELSE game_vault_balance END, game_available_balance = CASE WHEN UserID = '9915075' THEN 4.1253850908788 ELSE game_available_balance END, rating = CASE WHEN UserID = '9915075' THEN 0.24 ELSE rating END, game_rating_and_balance_update_last_time = CASE WHEN UserID = '9915075' THEN '2020-07-24 22:00:36' ELSE game_rating_and_balance_update_last_time END WHERE UserID IN('9915075')
Table structure:
CREATE TABLE `members` (
`id` int(10) UNSIGNED NOT NULL,
`UserID` varchar(64) NOT NULL,
`telegram_id` varchar(64) DEFAULT NULL,
`first_name` varchar(64) DEFAULT NULL,
`last_name` varchar(64) DEFAULT NULL,
`language` varchar(64) DEFAULT NULL,
`currency` varchar(64) DEFAULT NULL,
`status` varchar(64) DEFAULT NULL,
`rating` varchar(64) DEFAULT NULL,
`game_vault_balance` decimal(32,8) DEFAULT 0.00000000,
`game_available_balance` decimal(32,8) DEFAULT 0.00000000,
`game_rating_and_balance_update_last_time` datetime DEFAULT NULL,
`updated` datetime DEFAULT NULL,
`created` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Indexes of this table:
ALTER TABLE `members`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `UserID` (`UserID`) USING BTREE;
AUTO_INCREMENT for the members table:
ALTER TABLE `members`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
I asked a little ago, but I find my question so bad, that it actually didn't help me do what I wanted, so I deleted it and tried again.
I have a table in my database called 'game' with the columns: k1, k1r, k2, k2r, k3, k3r, grp and week. The week-column is automatically inserted with the week of the year and the others are user-inputs from a betting game I made.
Then I have a table called 'matches' with the columns: match1, match2, match3, grp, week. Again, same procedure with the week-column. The other 4 I fill out with the matches we should bet on. The 'grp' column in both is filled by me with 'BS' and 'VF'.
I then have a query:
SELECT *
FROM game
WHERE week = '.$week.' AND grp = 'bs';
$week is already set as $week = Date('W');
It outputs a table, where I write the matches in 3 columns and then echoes the users bets in the rows under the matches. But instead of me changing the php-script every time there are new matches, I would like it to take them from the table 'matches'. In that way, I also keep the old matches in the database.
So, now to my question :)
What I would like to do is something like:
'SELECT * FROM game WHERE week = '.$week.' AND grp = 'bs'
JOIN * FROM matches WHERE week = '.$week.' AND grp = 'bs';
but as you probably now, that won't work :/
In my other question I forgot to mention the 'grp' column and couldn't figure out how to insert it.
To echo it I used:
while ($row = mysqli_fetch_array($query)) {
$no = 1;
$amount = $row['amount'] == 0 ? '' : number_format($row['amount']);
echo '<tr>
<td><strong>'.$row['name'].'</strong></td>
<td>'.$row['k1']."<br />".$row['k1r'].'</td>
<td>'.$row['k2']."<br />".$row['k2r'].'</td>
<td>'.$row['k3']."<br />".$row['k3r'].'</td> }
but I would like an outcome like this:
| |Match1 |Match2 |Match3 |
|User1 |2-0 |2-1 |2-2 |
|User2 |1-1 |2-2 |1-2 |
And so on ... where the 'Matches' are selected from the 'matches'-table and the bets are selected from the 'game'-table. So I just need the one row from 'Matches' as the headline and then loop through the rows in 'Game'.
The creates are:
CREATE TABLE `game`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) DEFAULT NULL,
`user` varchar(20) COLLATE utf8_danish_ci DEFAULT NULL,
`name` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`k1` varchar(1) COLLATE utf8_danish_ci DEFAULT NULL,
`k1r` varchar(10) COLLATE utf8_danish_ci DEFAULT NULL,
`k2` varchar(1) COLLATE utf8_danish_ci DEFAULT NULL,
`k2r` varchar(10) COLLATE utf8_danish_ci DEFAULT NULL,
`k3` varchar(1) COLLATE utf8_danish_ci DEFAULT NULL,
`k3r` varchar(10) COLLATE utf8_danish_ci DEFAULT NULL,
`week` int(2) DEFAULT NULL,
`grp` varchar(11) COLLATE utf8_danish_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`uid`,`week`,`grp`)
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci
And:
CREATE TABLE `udvalgte_kampe`
(
`hold1` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`hold2` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`hold3` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`hold4` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`hold5` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`hold6` varchar(50) COLLATE utf8_danish_ci DEFAULT NULL,
`week` int(2) DEFAULT NULL,
`grp` varchar(11) COLLATE utf8_danish_ci DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci
But what should I do then?
Be aware for sql injection using $var and you can avoid string concatenation using proper quotes.
your second query the sintax for join is
is wrong youn should use this sintax
"SELECT * FROM game
JOIN matches on game.week = matches.week
where WHERE game.week = '$week' AND game.grp = 'bs'";
and not
'SELECT * FROM game WHERE week = '.$week.' AND grp = 'bs'
JOIN * FROM matches WHERE week = '.$week.' AND grp = 'bs';
If you use the SQL from the previous answer, I think this is roughly what you would need in your PHP :
$headerPrinted = $false;
while ($row = mysqli_fetch_array($query)) {
if (!headerPrinted) {
echo '<th>
<td></td>
<td>'.$row['hold1'].'</td>
<td>'.$row['hold2'].'</td>
<td>'.$row['hold3'].'</td>
</th>';
$headerPrinted = $true;
}
$no = 1;
$amount = $row['amount'] == 0 ? '' : number_format($row['amount']);
echo '<tr>
<td><strong>'.$row['name'].'</strong></td>
<td>'.$row['k1']."<br />".$row['k1r'].'</td>
<td>'.$row['k2']."<br />".$row['k2r'].'</td>
<td>'.$row['k3']."<br />".$row['k3r'].'</td>';
}
I'm making the assumption that hol1, hold2 and hold3 are the columns you want to use for your header.
I'm not saying this is the best way to achieve what you want, but it's probably good enough for your current level of experience.
Why is this query not showing more than one data. Even I have 10/12 data but this line only shows 1. Check I have limited it to 3 but it only shows 1.
$getAds = mysql_query("SELECT *
FROM advertises
WHERE status='RUNNING'
AND adult='0'
AND (country LIKE '%$test%' OR country='ALL')
AND (device LIKE '%$pabu%' OR device='ALL')
ORDER BY rand()
LIMIT 0,3");
my database structure
Table structure for table advertises --
CREATE TABLE `advertises` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userid` int(11) NOT NULL, `name` varchar(5000) NOT NULL, `url` varchar(5000) NOT NULL, `type` varchar(500) NOT NULL, `device` varchar(500) NOT NULL, `country` varchar(500) NOT NULL, `time` varchar(500) NOT NULL, `status` varchar(500) NOT NULL, `dset` varchar(500) NOT NULL, `cset` varchar(500) NOT NULL, `acpc` varchar(500) NOT NULL, `ucpc` varchar(500) NOT NULL, `adult` tinyint(10) unsigned NOT NULL DEFAULT '0', `title` varchar(500) NOT NULL, `pcpc` varchar(500) NOT NULL DEFAULT '0', `spent` varchar(500) NOT NULL DEFAULT '0', `adc` varchar(500) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
------ -- -- Dumping data for table advertises --
INSERT INTO `advertises` VALUES ('1','1','dqui.com/adultb.php','lt.adqui.com','banner','ALL','ALL','Saturday , September 19 , 2015','RUNNING','no','no','0.015','0.012','1','Android Adult','0.005','49999.925',''); INSERT INTO `advertises` VALUES ('2','1','http://adqui.com/banner.php','http://kid.adqui.com','banner','ALL','ALL','Saturday , September 19 , 2015','RUNNING','no','no','0.01','0.008','0','Android Non','0.002','49999.88','');
INSERT INTO `advertises` VALUES ('3','1','qui.com/adultb.php','lt.adqui.com','banner','ALL','ALL','Saturday , September 19 , 2015','RUNNING','no','no','0.0002','0.0002','1','Adult','0.00','4999.874','0.0002'); INSERT INTO `advertises` VALUES ('4','1','adqu i.com/banner.php','kid.adq ui.com','banner','ALL','ALL','Saturday , September 19 , 2015','RUNNING','no','no','0.0002','0.002','0','non','','4999.923','0.0008');
Status is a keyword in mysql. so try this
$getAds=mysql_query("SELECT * FROM advertises WHERE `status`='RUNNING' AND adult='0' AND (country LIKE '%test%' OR country='ALL') AND (device LIKE '%pabu%' OR device='ALL') ORDER BY rand() LIMIT 0,3");
Have you tried to use mysql_fetch_assoc on the result returned by mysql_query?
Refer to the mysql-query manual in particular Example #2
mysql_query() has already been deprecated, you can use PDO instead.
Try below,
<?php
$dbcon = new PDO("mysql:host=localhost;dbname=test", 'root', '');
$test = 'All';
$pabu = 'All';
$qry = "SELECT *
FROM advertises
WHERE status='RUNNING'
AND adult='0'
AND (country LIKE '%$test%' OR country='ALL')
AND (device LIKE '%$pabu%' OR device='ALL')
ORDER BY rand()
LIMIT 0,3";
$rq = $dbcon->query($qry);
$op = ( $rq ) ? $rq->fetchAll(PDO::FETCH_ASSOC) : '';
echo '<pre>'; print_r($op);
?>
I'm developing a page to edit board meetings and I want to display all board members who did not attend specific meeting as a checkox located below who attend as an edit in case of user want to add more so I did this:
My code:
$q = "SELECT * FROM `boardteam`";
$r = mysql_query($q);
while ($dbfield = mysql_fetch_assoc($r))
{
$member_id =$dbfield['nationalID'];
$query = "SELECT `attendance` FROM `meetingattendance` WHERE `meetingID` = '$mid' AND `attendance`!= '$member_id'";
$res = mysql_query($query);
if ($res)
{
$tname ="";
switch ($dbfield['titleName'])
{
case "Dr":
$tname .= "د.";
break;
case "Ms":
$tname .= "السيدة.";
break;
case "Mr":
$tname .= "السيد.";
break;
}
$At .= "<input type='checkbox' name='moreAttendence[]' dir='rtl' value=".$dbfield['nationalID']."><div class='styled-checkbox'>".$tname." ".$dbfield['fName']." ".$dbfield['sName']." ".$dbfield['lName']."</div><br>";
}
}
DB:
CREATE TABLE `boardteam` (
`nationalID` int(10) NOT NULL,
`titleName` char(2) NOT NULL,
`fName` char(20) NOT NULL,
`sName` char(20) NOT NULL,
`lName` char(20) NOT NULL,
`gender` char(1) NOT NULL,
`birthDate` date DEFAULT NULL,
`materialStatus` char(15) DEFAULT NULL,
`jobTitle` varchar(100) NOT NULL,
`jobLocation` varchar(20) DEFAULT NULL,
`employer` varchar(100) DEFAULT NULL,
`email` varchar(100) NOT NULL,
`photo` varchar(255) DEFAULT NULL,
`academicGrade` char(15) DEFAULT NULL,
`employmentStartDate` date NOT NULL,
`employmentEndDate` date NOT NULL,
`employmentType` char(20) DEFAULT NULL,
`employmentStatus` char(15) DEFAULT NULL,
`jobStartDate` date DEFAULT NULL,
`jobNumber` int(10) DEFAULT NULL,
`cv` varchar(255) DEFAULT NULL,
PRIMARY KEY (`nationalID`)
)
CREATE TABLE `meetingattendance` (
`meetingID` int(11) NOT NULL,
`attendance` int(10) DEFAULT NULL,
`absence` int(10) DEFAULT NULL,
`reason` varchar(255) DEFAULT NULL,
`additionalAttendance` varchar(255) DEFAULT NULL,
KEY `absence` (`absence`),
KEY `meeingID` (`meetingID`),
KEY `attendance` (`attendance`),
CONSTRAINT `meetingattendane_ibfk_1` FOREIGN KEY (`meetingID`) REFERENCES `boardmeetings` (`meetingID`),
CONSTRAINT `meetingattendane_ibfk_2` FOREIGN KEY (`attendance`) REFERENCES `boardteam` (`nationalID`),
CONSTRAINT `meetingattendane_ibfk_3` FOREIGN KEY (`absence`) REFERENCES `boardteam` (`nationalID`)
)
With my code I got all board members including who attend, How to fix that ??
You need to use a LEFT JOIN in order to find people in the boardTeam who were not in a specific meeting. eg:
SELECT b.*, m.attendance
FROM boardTeam b
LEFT JOIN meetingattendance m
ON b.nationalID = m.attendance AND m.meetingID = $mid
WHERE m.meetingID IS NULL
If you want to get ALL board members, and then determine within PHP if they attended the meeting or not, simply remove the m.attendance IS NULL clause, as such:
SELECT b.*, m.attendance as attendance
FROM boardTeam b
LEFT JOIN meetingattendance m
ON b.nationalID = m.attendance AND m.meetingID = $mid
and now when you loop through the response rows in php, you can test as such (assuming you fetch your rows one by one into a $row variable):
if($row['attendance'] != null)
{
// attended meeting
}
else
{
// did not attend meeting
}
Also, as mentioned in the comments, use mysqli, or pdo instead of pure mysql_ functions
Example fiddle here: http://sqlfiddle.com/#!9/ba7d4/6
I thought I was pretty good at this sort of thing but...
I have the following query from a customer table that is about 8,500 rows and an address table that is about the same number of rows.
This query takes about 10 seconds to complete and I can't figure how to get it to milliseconds.
What am I doing wrong?
<select>
<option value=""></option>
<?php // get the customers
$sql = "
SELECT `cust`.`custid`, `cust`.`custname`, `cust`.`custactive`, `address`.`addtype`, `address`.`address1`, `address`.`addcity`, `address`.`addstate`
FROM `cust`
LEFT Join `address`
ON `cust`.`custid` = `address`.`addcustid`
and `address`.`addtype` = 'b'
WHERE `cust`.`custactive` = 'y'"
;
$result = mysqli_query($con,$sql) or die('Query failed: Could not get list of CLIENTS: ' . mysqli_error($con)); // query
while ($row = mysqli_fetch_array($result)) {
$custid = $row['custid'];
$space="";
$endingspaces = 4-(2*strlen($prodid));
for($count=1; $count<$endingspaces; $count++){
$space .=" ";
}
$custid = $row['custid'];
$custname = substr($row['custname'],0,15);
$address1 = substr($row['address1'],0,15);
$addcity = substr($row['addcity'],0,15);
$addstate = $row['addstate'];
print "<option value=\"$custid\">$custid: $space$custname, $address1, $addcity, $addstate</option>";
}
?>
</select>
DDL:
CREATE TABLE `cust` (
`custid` int(11) DEFAULT NULL,
`custname` varchar(45) DEFAULT NULL,
`custactive` varchar(255) DEFAULT NULL,
`custcreated` varchar(255) DEFAULT NULL,
`custmodified` varchar(255) DEFAULT NULL,
`cust_dataease_custid` int(11) DEFAULT NULL,
`custtype` varchar(5) DEFAULT NULL,
`custrep` int(11) DEFAULT NULL,
`custsource` varchar(5) DEFAULT NULL,
`custdiscount` decimal(65,30) DEFAULT NULL,
`custrepcomm` varchar(255) DEFAULT NULL,
`custsurcharge` varchar(255) DEFAULT NULL,
`custterms` varchar(12) DEFAULT NULL,
`custups` varchar(255) DEFAULT NULL,
`custnotes` varchar(255) DEFAULT NULL,
`custbilldif` varchar(5) DEFAULT NULL,
UNIQUE KEY `custid` (`custid`),
KEY `cust_dataease_custid_idx` (`cust_dataease_custid`),
KEY `custrep_idx` (`custrep`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `address` (
`addid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`addcustid` int(11) unsigned NOT NULL,
`addname` varchar(200) DEFAULT NULL,
`addtype` enum('b','s') NOT NULL DEFAULT 'b',
`address1` varchar(150) NOT NULL,
`address2` varchar(150) DEFAULT NULL,
`addcity` varchar(150) DEFAULT NULL,
`addstate` varchar(150) DEFAULT NULL,
`addstateother` varchar(150) DEFAULT NULL,
`addzip` varchar(150) DEFAULT NULL,
`addcountry` varchar(150) DEFAULT NULL,
`addnote` tinyblob,
PRIMARY KEY (`addid`),
KEY `add_cust_id_idx` (`addcustid`)
) ENGINE=InnoDB AUTO_INCREMENT=13037 DEFAULT CHARSET=utf8
John Green got me to thinking about the way information was being sent to and from the server, which led me to find the problem. Thanks John.
This is how I fixed it: Apparently, when my loop was iterating, it was "printing" each of the 8500 OPTION lines, which action (i didn't know), is a server-client interaction. So for each row, the server and browser had to have a conversation, which slowed everything down.
I fixed it by having the server compile the entire SELECT box on the server side, including the opening SELECT tags and interacting with the browser once through echoing my "add-to" variable: $select_box.
Now it takes like 1.2 seconds. I can live with that.
Thanks everyone for helping me chase this rabbit.
<?php // get the products
$select_box = "<select name=\"customer\" id=\"customer\" onChange=\"getcustinfo();\" data-placeholder=\"Choose a Customer\" class=\"chosen-select\" style=\"width:227px;\" tabindex=\"1\">
<option value=\"\"></option>";
$sql = "
SELECT *
FROM `cust`
LEFT Join `address`
ON `cust`.`custid` = `address`.`addcustid`
and `address`.`addtype` = 'b'
WHERE `cust`.`custactive` = 'y'"
;
$result = mysqli_query($con,$sql) or die('Query failed: Could not get list of CLIENTS: ' . mysqli_error($con)); // query
while ($row = mysqli_fetch_array($result)) {
foreach ($row as $key => $value){ ${$key} = $value; }
$space="";
$custname = substr($row['custname'],0,15);
$address1 = substr($row['address1'],0,15);
$addcity = substr($row['addcity'],0,15);
$select_box .= "<option value=\"$custid\">$custid: $space$custname, $address1, $addcity, $addstate</option>";
}
$select_box .="</select>";
echo $select_box;
?>