Related
I am trying to pass a array in sql query.
Array contains coloumn names as index they are assigned to their respective values which i got using GET method.
for example iam trying to compile this code :
$a='email';
$b=array($a => $_GET['x']);
$sql="SELECT * FROM users WHERE $b";
echo $sql;
The output that i need is:
SELECT * FROM users WHERE email='/*value of $_GET['x']*/'
the output that i am getting is:
SELECT * FROM users where Array
can some one help me how to make it work.
You need to manipulate the $b array to make it into the string your after, at the moment it's just dumping the content in it's own format.
This version will do what your after...
$b=array($a => $_GET['x']);
$columns = [];
foreach ( $b as $name => $value ) {
$columns[] = "$name = '$value'";
}
$sql="SELECT * FROM users WHERE ".implode(" and ", $columns);
echo $sql.PHP_EOL;
I've made it use and as the condition linking multiple columns, you can change this depending on your requirement.
This version instead uses bind parameters, the place holder is inserted instead of the value in the query and then you will need to bind the $data array to the prepared statement (how depends in the API your using). This is safer and more flexible (and recommended)...
$b=array($a => $_GET['x']);
$columns = [];
$data = [];
foreach ( $b as $name => $value ) {
$columns[] = "$name = ?";
$data[] = $value;
}
$sql="SELECT * FROM users WHERE ".implode(" and ", $columns);
echo $sql.PHP_EOL;
I'm trying to combine two tables from a database, and based on my first one, I want to retrieve some value from the other one, and add them to an array.
Here's my problem:
My first database looks like that:
FIRST TABLE:
id, credit_type, association_name, address, city, province, postal_code, country, cycle_type, cycle_begin, cycle_months
My second database instead looks like that:
SECOND TABLE:
id, association_id, designation_name
The id in my first table matches the association_id in my second table so I don't need an INNER JOIN.
My approach is the following:
<?php
public function my_function()
{
$sql = ee()->db->select('*')->from('first_table')->get();
$data['database'] = [];
if ($sql->num_rows() > 0)
{
foreach($sql->result_array() as $row)
{
$id[] = $row['id'];
$data['database'][] = $row;
}
}
foreach ($data['database'] as $key => $value) {
$association_query = ee()->db->query("SELECT * FROM second_table WHERE id = $id");
foreach($association_query->result_array() as $row_two)
{
if ($association_query->num_rows() > 0)
{
$data['database'][$key]['associations'][] = $row_two['designation_name'];
}
}
}
return ee()->load->view('index', $data, true);
}
?>
The sintax ee()->db->select('*') is a prepared statment from expression engine and it's equal to SELECT * FROM first_table (sanitaized).
So as you can see, I try to pass the value $id, which is an array, to my query. The thing is that as soon as I push the value like that $id[] = $row['id'] I create a nice array, but when I loop through my foreach loop, it multiplies my array in many other arrays so I'm not able to run my query, even if I'm technically in a foreach loop.
Plus, as soon as I try to push the result of my query in my array, let's say changing the id in a static id for instance id=3, I obtain a really weird result, like so many arrays repeated with 1 value, 2 value, 3 value and so on, when I'd like to push my key 'association' only where it is presented in the other table.
If you won't do it on SQL, at least don't execute the second query so many times.
<?php
public function my_function()
{
$assocs = array();
$data = array('database' => array());
$association_query = ee()->db->query("SELECT * FROM second_table");
if ($association_query->num_rows() > 0) {
foreach($association_query->result_array() as $row) {
$assocs[$row['association_id'][] = $row['designation_name'];
}
}
$sql = ee()->db->select('*')->from('first_table')->get();
if ($sql->num_rows() > 0) {
foreach($sql->result_array() as $row) {
$id_check = $row['id'];
if (isset($assocs[$id_check])) {
$row ['associations'] = $assocs[$id_check] ;
}
$data['database'][] = $row;
}
}
return ee()->load->view('index', $data, true);
}
?>
Regards
I have data coming back from MySQL and the goal is to pull data from multiple servers.
The data can be grouped by one or more fields, and I want to pull data from X number of MySQL servers and sum the data that should be summed, using the other data as a key or index.
Example:
Result from Mysql[$x]:
[{"date":"2017-10-10","account":"1","trees":"1","people":"0","pets":"4"}
,{"date":"2017-10-10","account":"2","trees":"2","people":"5","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"3","people":"3","pets":"4"}
,{"date":"2017-10-11","account":"2","trees":"4","people":"1","pets":"4"}]
Result from Mysql[$x+1]:
[{"date":"2017-10-10","account":"1","trees":"5","people":"1","pets":"1"}
,{"date":"2017-10-10","account":"2","trees":"5","people":"2","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"5","people":"0","pets":"2"}
,{"date":"2017-10-11","account":"2","trees":"5","people":"1","pets":"2"}]
Desired end result:
[{"date":"2017-10-10","account":"1","trees":"6","people":"1","pets":"5"}
,{"date":"2017-10-10","account":"2","trees":"7","people":"7","pets":"2"}
,{"date":"2017-10-11","account":"1","trees":"8","people":"3","pets":"6"}
,{"date":"2017-10-11","account":"2","trees":"9","people":"2","pets":"6"}]
in this case, there are 2 keys, date and account, but in reality there can be between 1 and 4.
The grouping keys are known, so the code knows that in this case, date and account are the keys.
I'm trying to find a better way than iterating through each row of mysql[$x] and then iterating through each row of mysql[$x+1] ... mysql[$x+n] and checking each value of the known keys to see if they match the current row's key values and then summing the data.
Also note that in reality, there may not be a row for each set of keys, hence the number and order of rows from each server can be variable.
I need an efficient way to do this because there are potentially tens of thousands of rows with a dozen+ columns.
I'm experimenting with code like this:
$res = array();
$keys = array('date','account');
array_walk($t,'rehash',$res);
function rehash($data,$key,&$result) {
global $keys;
global $res;
$keydata = array_slice($data,0,count($keys));
$vals = array_slice($data,count($keys));
//this is how the data would ideally be structured, my model
//$res[$keydata[$keys[0]]][$keydata[$keys[1]]] = $vals;
//this code below successfully creates rows in the right format
for($x = count($keys) - 1; $x>= 0; $x--) {
if($x == count($keys)-1) {
$tmp = array($keydata[$keys[$x]] => $vals);
//} else if($x ==0) {
// maybe reconcile here?
} else {
$tmp = array($keydata[$keys[$x]] => $tmp);
}
}
}
But how do i reconcile this? I can't simply do $res[key1] = $tmp[key1] because with multiple keys it would remove all the other rows.
Also with nested arrays, how would I iterate through each nested array if the number of levels is variable?
Lastly if I do this, I would need to convert it back into the original format for the frontend, so... joy. :D (this part would be easy, just is worth taking into consideration from an efficiency standpoint)
You don't need to use array_walk, since your data isn't hierarchical. Just use an ordinary foreach loop.
$res = array();
foreach ($t as $row) {
$cur = &$res;
// Drill down into result array using the key fields, creating nested arrays
// as necessary
foreach ($keys as $keycol) {
$key = $row[$keycol];
if (!isset($cur[$key])) {
$cur[$key] = array();
}
$cur = &$cur[$key];
}
// Now go through the data columns in the row, adding them to the totals
foreach ($row as $key => $val) {
if (in_array($key, $keys)) {
// Put the key fields in the result row
$cur[$key] = $val;
} else {
// Accumulate other values in the result row
if (!isset($cur[$key])) {
$cur[$key] = 0;
}
$cur[$key] += $row[$key];
}
}
unset($cur); // Break the reference link
}
Here is a possible solution based on the structure of the sample data given in the question.
$jsn1 = '[{"date":"2017-10-10","account":"1","trees":"1","people":"0","pets":"4"}
,{"date":"2017-10-10","account":"2","trees":"2","people":"5","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"3","people":"3","pets":"4"}
,{"date":"2017-10-11","account":"2","trees":"4","people":"1","pets":"4"}]';
$jsn2 = '[{"date":"2017-10-10","account":"1","trees":"5","people":"1","pets":"1"}
,{"date":"2017-10-10","account":"2","trees":"5","people":"2","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"5","people":"0","pets":"2"}
,{"date":"2017-10-11","account":"2","trees":"5","people":"1","pets":"2"}]';
/* Decode the json strings into associative arrays: */
$arr1 = json_decode($jsn1, true);
$arr2 = json_decode($jsn2, true);
/* Put in an array the keys whose values are to be added: */
/* Do not include date and account keys if they are not to be added */
$arr_keys = ['trees', 'people', 'pets'];
/* Loop through both $arr1 and $arr2 while storing new arrays in arr: */
/* Be adding up the values for the keys that are in $arr_keys */
$arr = [];
foreach($arr1 as $k => $v){
$arr[$k]['date'] = $arr1[$k]['date']; $arr[$k]['account'] = $arr1[$k]['account'];
foreach($arr_keys as $y){
if($arr1[$k][$y] !== null && $arr2[$k][$y] !== null){
$arr[$k][$y] = $arr1[$k][$y] + $arr2[$k][$y];
}}}
/* encode the array to the required json string: */
$json = json_encode($arr);
echo $json;
/* Output:
[{"date":"2017-10-10","account":"1","trees":"6","people":"1","pets":"5"}
,{"date":"2017-10-10","account":"2","trees":"7","people":"7","pets":"2"}
,{"date":"2017-10-11","account":"1","trees":"8","people":"3","pets":"6"}
,{"date":"2017-10-11","account":"2","trees":"9","people":"2","pets":"6"}]
*/
I am trying to get data from a database that meets multiple criteria of an array.
The array is something like this:
Array ([21] => 1,[23] => 0,[19] => 1);
With the key being a Question ID and the values being either yes or no.
I need to find the movie where the value for question_id = 21 is 1, value for question_id = 23 is 0 and value for question_id = 19 is 1. The way I have them stored is like this:
So my first thought was get the data for each and then put them in a bigger array. If the movie shows up the same amount of times as the number of elements in the array, then I consider it a good match. But this seems inefficient. I would rather just find the movies that match the criteria.
Since there are movie_id records with the same value, is there a way to write something like this?:
foreach($array as $key=>$value){
$i++;
$this->db->where('question_id', $key);
$this->db->where('value', $value);
}
$this->db->from('movies_values');
$query = $this->db->get();
$res = $query->result();
array_push($main,$res);
The thought behind this is to create a loop of all the WHEREs. And then run the query using those where values. This doesn't seem to work, is there something else I can do?
How about using WHERE IN (array())?
From the CI User Guide:
$names = array('Frank', 'Todd', 'James');
$this->db->where_in('username', $names);
// Produces: WHERE username IN ('Frank', 'Todd', 'James')
Use the where_in method for lists:
$this->db->where_in('value', $array);
Try doing it like this.
$where = WHERE 1
foreach($array as $key=>$value){
$where .= " AND(question_id = $key AND value = $value)";
}
$this->db->where($where);
PS. What is the $i++ doing in your loop exactly?
I think this is the right way to go, you should take care to use "or" instead to use full "ands" that way would not return any row due to a logic problem (I mean question_id = 1 and value = 1 and question_id = 2 and value = 0 we're being inconsistent due to telling that we want question_id = 1 and question_id = 2 won't match nothing!, the same applies to "values").
$array = array(21 => 1,23 => 0,19 => 1);
$where = array();
foreach($array as $key => $value) {
$where[] = "(question_id=$key and value=$value)";
}
var_dump($where);
foreach ($where as $value) {
$this->db->or_where($value);
}
$q = $this->db->get('movies_values')->result();
var_dump($q);
echo $this->db->last_query();exit;
This can be done easily without loop:
$filter = array(21 => 1,23 => 0,19 => 1);
$values = implode(',',array_unique(array_values($filter))); // results into 0,1...
$keys = implode(',',array_unique(array_keys($filter))); // results into 19,21,23...
$result = $this->db
->query("select * from movies_values
where
question_id in(".$keys.")
and value in(".$values.")")
->result();
Happy coding ---> :)
I need to sort an associative-array in the exact order of the content of another array.
The Arrays are retrieve by 2 separate sql-requests (stated below). The requests could not be combined to only one request, so I have to sort the second array into the order of the first one.
These are the arrays:
#Array which contains the id's in needed order
$sorting_array = array(1,2,3,8,5,6,7,9,11,10...);
#Array which contains the values for the id's, but in order of "id" ASC
$array_to_sort = array(
array("id" => "1", "name" => "text1", "help" => "helptxt2");
array("id" => "2", "name" => "text2", "help" => "helptxt2");
);
The SQL-Queries:
SQL-Ouery for $sorting_array: (the db-field 'conf' is setup as "text", maybe this is my problem so that I have to first explode and implode the entries before I could use it for the next query.)
$result = sql_query("select conf from config where user='me'", $dbi);
$conf = sql_fetch_array($result, $dbi);
$temp = explode(',', $conf[0]);
$new = array($temp[0], $temp[1], $temp[2], $temp[3],$temp[4],
$temp[5], $temp[6], $temp[7], $temp[8], $temp[9],
$temp[10], ...);#Array has max 30 entries, so I count them down here
$sorting_array = implode(',', $new);
SQL-Ouery for $array_to_sort:
$result = sql_query("SELECT id, name, helptxt
FROM table
WHERE id IN ($sorting_array)
AND language='english'");
while ($array_to_sort[] = mysql_fetch_array ($result, MYSQL_ASSOC)) {}
array_pop($array_to_sort);#deleting the last null entry
I could access $array_to_sort as follows to see the content one by one:
(if the lines below don't match the array above, than I mixed it up. However, the lines below is what brings the content)
echo $array_to_sort[0]["id"];
echo $array_to_sort[0]["name"];
echo $array_to_sort[0]["helptxt"];
But it is sorted by "id" ASC, but I need exactly the sorting as in $sorting_array.
I tried some things with:
while(list(,$array_to_sort) = each($sorting_array)){
$i++;
echo $array_to_sort . "<br>";
}
which only brings the Id's in the correct order, but not the content. Now I'm a bit confused, as I tried so many things, but all ended up in giving me the same results.
Maybe the sql-query could be done in one step, but I didn't brought it to work.
All results to my searches just showed how to sort ASC or DESC, but not what I want.
Furthermore I must confess that I'm relative new to PHP and MySQL.
Hopefully some one of you all could bring me back on track.
Many thanks in advance.
To fetch your results:
$result = mysql_query("SELECT id, name, helptxt
FROM table
WHERE id IN ($sorting_array)
AND language='english'");
$array_to_sort = array();
while ( ($row = mysql_fetch_assoc($result)) !== false ) {
// associate the row array with its id
$array_to_sort[ $row[ "id" ] ] = $row;
}
To display them in order of $sorting_array:
foreach ( $sorting_array as $id ) {
// replace the print_r with your display code here
print_r( $array_to_sort[ $id ] );
}
And a bonus tip for the code fetching $sorting_array:
$result = mysql_query("select conf from config where user='me'", $dbi);
$conf = mysql_fetch_array($result, $dbi);
$temp = explode(',', $conf[0]);
// limit to 30 ids
$new = array();
// no need to do this manually, use a loop
for ( $i = 0; $i < 30; ++$i )
$new[] = $temp[ 0 ];
$sorting_array = implode(',', $new);
Its a little hard to tell because there is a lot going on here, in the future you'll probably get better/more responses if you ask several simple questions and figure out yourself how to make the answers fit together.
Your best bet long term is going to be to restructure your SQL tablessuch that you can combine these query together. You can do what you're asking in PHP, but it's going to be slower than doing it in MySQL and much more complicated.
To do what you're asking (pretty slow in PHP):
$sorted = array();
foreach ( $sorting_array as $id )
{
foreach ( $array_to_sort as $values )
{
if ( $values['id'] == $id )
{
$sorted[] = $values;
break;
}
}
}
what I tend to do in such a situation is first to rearrange the array with the data. so the keys represent ids
In your case:
$array_to_sort_ids = array();
foreach ($array_to_sor as $item)
{
$array_to_sort_ids[$item['id']] = $item;
}
Then sorting is as simple as:
$array_sorted = array();
foreach ($sorting_array as $id)
{
$array_sorted[] = $array_to_sort_ids[$id];
}
This solution is quite efficient, since you only have 2 foreach loops.
EDIT!!!
As I couldn't edit my question anymore, I just like to state my solution this way:
The tip to rethink my database was what brought me to some testings and then I found the solution, with the following query:
$result = sql_query("SELECT id, name, helptxt
FROM table
WHERE id IN ($sorting_array)
AND language='english'
ORDER BY FIELD(id,$sorting_array)");
while ($array_to_sort[] = mysql_fetch_array ($result, MYSQL_ASSOC)) {}
array_pop($array_to_sort);#deleting the last null entry
Just the line:
ORDER BY FIELD(id,$sorting_array)
will do the trick. It orders the results the way you want, even if this means 1,4,2,3,9,7,...
Sometimes it's so easy, when you know where to look.
Thanks again!!!