How to search through multiple columns in mysql - php

This is part of the query where it supposed to search through morning, afternoon and evening columns in posts table.
$add_here .= " AND posts.".$col." IN ('" . implode("',' ",$days) . "')";
$col is the variable that holds array or single value for column name supplied by user. Namely 'morning','afternoon','evening'. Do you know how to alter the query above to search in the array($col)?
The below works because I specified column name which is 'afternoon'. I wonder how to replace the text 'afternoon' with array of values!
$add_here .= " AND posts.afternoon IN ('" . implode("',' ",$days) . "')";

Use array_map to build a series of conditions grouped with OR :
$days = ['sun','mon','tue'];
$col = ['afternoon','morning','night'];
$add_here = '';
$add_here .= sprintf(" AND (%s)",
implode(' OR ', array_map(
function($colx) use ($days) {
return sprintf("posts.%s IN ('%s')", $colx, implode("','",$days));
}, is_array($col) ? $col : array($col))
)
);
AND (posts.afternoon IN ('sun','mon','tue') OR posts.morning IN
('sun','mon','tue') OR posts.night IN ('sun','mon','tue'))

Related

php array_map is not mapping arrays correctly

I am fetching data from db.I am looping over the sql query and array_map() to get proper value.
$CompleteData = array();
foreach ( $Details as $d ) {
$q = "SELECT "
. "`log`.`id` AS 'id', "
. "DATE_FORMAT( `log`.`timestamp`, '%d %b %Y %h:%i:%s %p' ) AS 'timestamp', "
. "`log`.`Author` AS 'Author', "
. "`log`.`message` AS 'message', "
. "`log`.`bookname` AS 'bookname' "
. "FROM `log` "
. "WHERE `log`.`detailId` = '" . $d . "' "
. "ORDER BY `log`.`timestamp` DESC, `log`.`id` DESC";
$qr = mysql_query($q, $sql);
for ($i = 0; $i < mysql_num_rows($qr); ++$i) {
$LogId[$i] = mysql_result($qr, $i, 'id');
$LogTimestamp[$i] = mysql_result($qr, $i, 'timestamp');
$LogAuthor[$i] = mysql_result($qr, $i, 'Author');
$LogMessage[$i] = mysql_result($qr, $i, 'shortmessage');
$Logbookname[$i] = mysql_result($qr, $i, 'bookname');
}
$CompleteData[$d] = array_map(null, $LogId, $LogTimestamp, $LogAuthor, $LogMessage, $Logbookname);
}
Here array_map is not mapping data as desired and the output is collapsed.
Log table in DB:
Desired Output:
But with array_map(null,array1,arrar3..) the output is like below
It is combining 1st array with 2nd array and so on.
Can you pls tell am I doing wrong with array map?
I think you are doing it really wrong.
First I would like to inform you that mysql_ functions are deprecated and it's better starting looking for PDO, mysqli_ functions or MySQLi class and, of course, prepared statements.
What you are trying to do can be simplified as follows:
$query = "SELECT "
. "`log`.`id` AS 'id', "
. "DATE_FORMAT( `log`.`timestamp`, '%d %b %Y %h:%i:%s %p' ) AS 'timestamp', "
. "`log`.`Author` AS 'Author', "
. "`log`.`message` AS 'message', "
. "`log`.`bookname` AS 'bookname' "
. "FROM `log` "
. "WHERE `log`.`detailId` IN ('" . implode("', '", $Details) . "') "
. "ORDER BY `log`.`timestamp` DESC, `log`.`id` DESC";
$stmt = mysql_query($query);
$CompleteData = array();
while ($row = mysql_fetch_array($stmt)) {
if (!isset($CompleteData[$row['detailedId']])) {
$CompleteData[$row['detailedId']] = array($row);
} else {
$CompleteData[$row['detailedId']][] = $row;
}
}
Why is better this way?
You are executing a single query to get the info for all the logs
The complexity of the code is smaller so the execution will be faster
The code is more readable and easy to understand
Later edit:
If your $Details variable is an array of objects you can use array_map to get only the info you need to use in the query:
$detailsIds = array_map(function ($item) {
return $item->detailsId;
}, $Details);
having the details ids you can use the array to create the where statement:
"WHERE `log`.`detailId` IN ('" . implode("', '", $detailsIds) . "')
I think an associative array will format your response with the columns without the need to use array map.
Associative array

PHP MySQL large quantity of queries being passed,

I have a PHP script that is passing large quantities of queries to a DB very quickly. Does a MySQL DB queue the queries as they come in if it can't process them at the same speed they are being passed, or do they get lost?
My program has written and passed syntactically correct queries to the DB, but the DB is very far behind in terms of information contained in tables and number of tables.
Some example code (I am slightly new to PHP, so my code/coding style may be horrifying):
//If table has one primary key
$val = $tblColPkArray[0];
$pkInsert = ", PRIMARY KEY (". $val['COLUMN_NAME'] .")";
$pkColName = $val['COLUMN_NAME'];
$string = ltrim($string, ",");
$oneCreateTableQuery = $beginning . $string . $pkInsert . $end;
echo $oneCreateTableQuery . "\n";
$newLink->query($oneCreateTableQuery);
$pkValuesInOld = "SELECT " . $pkColName . " FROM " . $tables . ";";
$pkValsResult = $link->query($pkValuesInOld);
while($pkValues = $pkValsResult->fetch(PDO::FETCH_ASSOC))
{
$pkRowValuesQuery = "SELECT * FROM " . $tables . " WHERE " . $pkColName . " = '" . $pkValues[$pkColName] . "';";
echo $pkRowValuesQuery . "\n";
$valsOfPkInOldTable = $link->query($pkRowValuesQuery);
while($pkVals = $valsOfPkInOldTable->fetch(PDO::FETCH_ASSOC))
{
//var_dump($ckVals);
$insertBeginning = "INSERT INTO " . $tables . "(";
$insertValuesSection = ") VALUES (";
$insertEnd = ");";
$keys = "";
$rowValues = "";
foreach($pkVals as $key => $value)
{
$keys = $keys . ", " . $key;
$rowValues = $rowValues . ", '" . $value . "'";
}
$insertStatement = $insertBeginning . ltrim($keys, ",") . $insertValuesSection . ltrim($rowValues, ",") . $insertEnd;
echo $insertStatement . "\n";
$newLink->query($insertStatement);
}//While loop: Inserting values of old table into new table via INSERT INTO statement
//unset();
} //While loop: Selecting all values from old table based on PK values per table, pass result of that query to next while loop
You can do this in a single query, instead of calling multiple insert statements.
For instance, instead of running these 3 queries,
INSERT INTO table VALUES(1, 2);
INSERT INTO table VALUES(3, 4);
INSERT INTO table VALUES(5, 6);
...
You could run this query:
INSERT INTO table VALUES(1, 2), (3, 4), (5, 6), ...;
Looks like you could do even combine the INSERT and SELECT:
INSERT INTO table (...)
SELECT ... FROM ...;
Furthermore, your nested loops look like this might work:
INSERT INTO table (...)
SELECT ... FROM ...
JOIN ...;
That would get it down to one call to ->query() and eliminate most of your code.

Update multiple rows in Mysql

I have a sql table in my database "accounts" whose structure looks like this.
ItemNo CostPrice SellingPrice Discount(10%) Price(INR)
100 $100 $150 $135 Rs.7425
101 $200 $250 $225 Rs.10395
102 $150 $200 $180 Rs.7920
103 $500 $550 $495 Rs.25245
Here each column is dependent on the previous one.
SellingPrice = CostPrice + 50
Discount = SellingPrice + (0.1 * SellingPrice)
Price(INR) = SellingPrice * ($_Conversion_rate_to_Rs)
I need to calculate the SellingPrice and update it in the table.
Then I calculate the Discount and update the table
Then I calculate the Price(INR) and update the table.
I am trying the following code but it doesnt seem to be working.
$i = 0;
foreach($item_no as $item ){
mysql_query("UPDATE accounts SET SellingPrice = CostPrice + 50 WHERE item_no = '$item[$i]'") or die(mysql_error());
++$i;
}
Now after updating the SellingPrice I need to calculate the discount and update the database.
$i = 0;
foreach($item_no as $item ){
mysql_query("UPDATE accounts SET Discount = SellingPrice + (0.1 * SellingPrice) WHERE item_no = '$item[$i]'") or die(mysql_error());
++$i;
}
And so on..
My doubt may be quite simple but I tried a lot and couldn find a correct solution.
Can I know my mistakes and the correct solution ?
EDIT!
The way I edit multiple fields is with a custom update function. The function takes an associative array of "field"=>"new value". Here's the function:
function update($table,$values,$conditions){
$query = "UPDATE `" . $table . "` SET ";
foreach($values as $key => $value){
if($key == "password")
$query .= "`password` = PASSWORD('" . $mysqli->real_escape_string($value) . "'),";
else if(is_numeric($value))
$query .= "`" . $mysqli->real_escape_string($key) . "` = " . $mysqli->real_escape_string($value) . ",";
else
$query .= "`" . $mysqli->real_escape_string($key) . "` = '" . sanitize($value) . "',";
}
$query = substr($query,0,-1);
if(!is_string($conditions)){
$conditionStr = "";
foreach($conditions as $key => $value){
if($key == "password")
$conditionStr .= "`password` = PASSWORD('" . $mysqli->real_escape_string($value) . "') AND ";
else if(is_numeric($value))
$conditionStr .= "`" . $mysqli->real_escape_string($key) . "` = " . $mysqli->real_escape_string($value) . " AND ";
else
$conditionStr .= "`" . $mysqli->real_escape_string($key) . "` = '" . sanitize($value) . "' AND ";
}
$conditionStr .= substr($conditionStr,0,-4);
$conditions = $conditionStr;
}
$query .= " WHERE " . $conditions . " ;";
$mysqli->query($query);
}
You use it like this:
update("theTable",array("username"=>"whateverTheNewNameIs"),array("userID"=>55));
That updates userID=55 and makes the username something new. You can just expand the second array to update more things.
I think you a problem in your updates and your where clause
I'd make a variable for your new cost price,
$newSellingPrice = $item[$i]['sellingPrice'] + 50;
In your update you can use $newSellingPrice
Then in your where, you have a typo, you didn't use the $ to get the item array.
You'll need to leave the query string if you're using square bracket notation
"... WHERE item_no = " . $item[$i] . " ;";
To answer your question, if you want to update all fields in the table, there is no need to add a WHERE condition, you can just use:
UPDATE accounts SET SellingPrice = CostPrice + 50
and run only one query in total instead of one query per item.
However, all columns that depend on other columns really don't need to be separate columns, you would be a lot better of with a table with just 2 columns and calculate the prices as you need them. Now you have a lot of duplicate information as the cost price and the multipliers are the only values you really need to store.

Trying to extract 5 characters from a column when adding record mysql via php

My part_no column has the following format: 000-00000-00 for all records.
I need to extract the five middle characters from part_no and place it in the core column when I create the record.
I can't get my script to work.
I'm not getting any errors. Just not working.
$order = "INSERT INTO cartons_added (add_time, type, part_no, add_type, add_qty, add_ref, add_by, add_notes)
VALUES
('$date',
'$_POST[type]',
'$_POST[part_no]',
'$_POST[add_type]',
'$_POST[add_qty]',
'$_POST[add_ref]',
'$_POST[add_by]',
'$_POST[add_notes]')";
$result = mysql_query($order);
$query2 = "select part_no from cartons_current";
$sel = mysql_query($query2);
$res = mysql_result($sel);
while($row = mysql_fetch_row($res)) {
$core_digits = split('-',$row[0]);
$core =$core_digits[1];
$query3 = "insert into cartons_current(core) values($core)";
$sel2 = mysql_query($query3);
}
You can update your cartons_current table based on your cartons_added table with something like:
INSERT INTO cartons_current(core)
SELECT SUBSTR(part_no, 5, 5) FROM cartons_added
You will probably want to limit that with a WHERE clause or maybe deal with what happens when this value is already in cartons_current (use either INSERT IGNORE or ON DUPLICATE KEY UPDATE)
You are right, the script has no error.
I think the problem is on your SQL that made you can't insert a new row, specifically on the table structure. Maybe you defined a PRIMARY KEY without AUTO_INCREMENT, defined a INDEX or UNIQUE key that is not the core key or there have some other key that did not have default value. Remember that you can't insert a row without defining all required field.
You script is selecting all part_no and for every part_no you are inserting a new row in the same table, so maybe there is the problem.
I think what you want is update every result to add they core value, you can do that with UPDATE as this code:
function getValue($value) {
return "'" . trim(mysql_real_escape_string($value)) . "'";
}
mysql_query('INSERT INTO `cartons_added` (`add_time`, `type`, `part_no`, `add_type`, `add_qty`, `add_ref`, `add_by`, `add_notes`)
VALUES (' .
getValue($date) . ', ' .
getValue($_POST[type]) . ', ' .
getValue($_POST[part_no]) . ', ' .
getValue($_POST[add_type]) . ', ' .
getValue($_POST[add_qty]) . ', ' .
getValue($_POST[add_ref]) . ', ' .
getValue($_POST[add_by]) . ', ' .
getValue($_POST[add_notes]) .
')');
$partNoQuery = mysql_query('SELECT `part_no` FROM `cartons_current`');
while($partNoResult = mysql_fetch_assoc($partNoQuery)) {
list($prefix, $core, $suffix) = explode('-', $partNoResult['part_no']);
mysql_query('UPDATE cartons_current SET `core` = \'' . $core . '\' WHERE `part_no` = \'' . $partNoResult['part_no'] . '\'');
}
I added getValue function to escape posted data to prevent SQL injection.
Try removing this
$res = mysql_result($sel);
And change your while to reference the main query resource
while($row = mysql_fetch_row($sel)) {
I don't understand your logic with your tables though. You're inserting data into the cartons_added table but then you're selecting from cartons_current?
Also, split is deprecated as of PHP 5.3.0
You said five middle "characters", so I'd add quotes around your variable like so:
$query3 = "insert into cartons_current(core) values('$core')";
(Also, there's only about a gazillion answers on SO about SQL injection, and using pdo)
INSERT INTO cartons_current(core)
SELECT
substr(part_no,position('-' IN part_no)+1,position('-' IN substr(part_no,position('-' IN part_no)+1))-1)
FROM cartons_added;

Optimize this SQL query

I've got a SQL query within a foreach loop. Sometimes there can be many, and I mean a lot of queries to do, depending on several criteria, up to 78 queries potentially.
Now, I know that premature optimisation is root cause of all evil, but I don't want to see 78 queries - it's just not healthy.
Here's the code:
$crumbs = explode(",", $user['data']['depts']);
foreach ($crumbs as &$value) {
$data = $db->query("SELECT id FROM tbl_depts WHERE id = '" . $value . "'");
$crumb = $data->fetch_assoc();
$dsn = $db->query("SELECT msg, datetime FROM tbl_motd WHERE deptid = '" . $value . "'");
$motd = $dsn->fetch_assoc();
if ($motd['msg'] != "") {
<?php echo $motd['msg']; ?>
}
}
Can I make it any better?
Use IN MySQL operator to search over a set of values for id:
$ids = '"' . implode('", "',$crumbs) . '"';
$query1 = "SELECT id FROM tbl_depts WHERE id IN (" . $ids . ")";
$query2 = "SELECT msg, datetime FROM tbl_motd WHERE deptid IN (" . $ids . ")";
And so you will not need to retrieve all data you need using foreach loop, so you will have only 2 queries instead of 78.
Example: I have a table named table with 10 records which ids are: 1,2,3,4,5,6,7,8,9,10 (auto-incremented). I know I need records with ids 1,5,8. My query will be:
$sql = "SELECT * FROM `table` WHERE id in (1,5,8);";
And I don't understand why do you need to use & operator in foreach loop if you don't modify the $crubms arrays values.
I think this is want you want.
SELECT msg, datetime
FROM tbl_depts td
INNER JOIN tbl_motd tm ON td.id = tm.deptid

Categories