This question already has answers here:
Natural ORDER in Laravel Eloquent ORM
(5 answers)
How to Sort a Multi-dimensional Array by Value
(16 answers)
Closed 6 months ago.
MySQL Database table
Rates:
Id
Name
1
$13.00
2
$20.00
3
$13.75
4
$15.00
5
$100.00
I'm trying to sort the data ASC to show on the dropdown, based on the data you can clearly understand that we can't sort the data by Id.
Here is the same code
$sorted = $rates;
foreach ($rates as $key => $data){
if(preg_match('/[a-z]/', $data['name'])){
unset($sorted[$key]);
$sorted[] = $data;
}
}
Result:
Dropdown
Expected Result:
$13.00
$13.75
$15.00
$100.00
Can you help me to figure this out?
You can try this:
$collection = collect([
['price' => '$13.00'],
['price' => '$12.00'],
['price' => '$15.00'],
]);
$sorted = $collection->sortBy('price');
dd($sorted);
it's very simple instead of sorting data in php, sort data when query table
first of all delete $ in name column and save data as float and change column data type to float
now you can feel sql power
if you want to run sql query manually use this query below
select * from Rates order by Name asc
if you want to use laravel eloquent use this code below
Rate::orderBy('Name','asc')->get();
for more information about order in mysql query see this or in laravel eloquent see this
Guessing ur using eloquent u can sort data when getting it from databse with orderBy
$query = Model::class('params')->orderBy('name', 'asc')->get();
Then when u do #foreach for printing it would be ID for the one with lowest price up until highest, and u dont have to deal with collections.
There is no need to delete your $ sign and change your data structure.
Related
I have this following Yii 2 query
$find = People::find()->where(['c_id' => $c_id])->orderBy('totals DESC, id DESC')->all();
So imagine this query was an array. Everything found by this query has an "id" attribute.
Since it's sorted by "totals", I essentially want to return the position in the array where I can find this specific id.
Currently, I'm using this code.
foreach ($find as $t) {
$arr[] = $t->id;
if ($t->id == $id) {
break;
}
}
$key = count($arr);
return $key;
However, this code is vany wayow on a 100k+ result query.
Is there anyway to speed this up?
You could get the result as an array (instead of object) as
$find = People::find()->where(['c_id' => $c_id])
->orderBy('totals DESC, id DESC')
->asArray()
->all();
then you could find your value using array_search()
$my_index = array_search($id,$find);
but for 100k+ you should find using a direct select in db...instead tha looping on php or load all in php and scan with array_search()
To get array from query in YII, you can use queryAll();
$find = People::find()->where(['c_id' => $c_id])->orderBy('totals DESC, id DESC')->queryAll();
OR, another way to convert the object into an array is:
$find = json_decode(json_encode($find), true); // to convert all data into array.
And once you get results in array, you can implement the actual code for your requirement as given below.
You can use array_search() function to get index of your value.
$a=array("a"=>"red","b"=>"green","c"=>"blue");
echo array_search("red",$a);
The array_search() function search an array for a value and returns the key.
Maybe I didn't understand you correctly but I assume that you are trying to detect the index or key for your desired id inside an array returned from an SQL query that is sorted by some other column like total.
So let us fetch records from the database with your query with a little change asArray() like this
$find = People::find()
->where(['c_id' => $c_id])
->orderBy('totals DESC, id DESC')
->asArray()
->all();
in the result, let us assume the People table returns you an array with the following dataset ordered by columns total and id DESC.
[
0 => [
'id' => 2 ,
'c_id'=>2,
'name' => 'John' ,
'age'=>18,
'totals'=>100,
],
1=>[
'id'=>1,
'c_id'=>55,
'name'=>'Bob',
'age'=>20,
'totals'=>80,
],
2=>[
'id'=>3,
'c_id'=>85,
'name'=>'Peter',
'age'=>15,
'totals'=>75,
]
];
Now if you look into \yii\helpers\ArrayHelper you will find ArrayHelper::getColumn().
Let us use this on the array we received from the query, I assume that you are searching $id inside the column id so we will first filter out the id column like below.
$idsArray = ArrayHelper::getColumn($find, 'id');
this will give us the ids in the following sequence which is in the same order as the initial result set.
[2,1,3]
then lets use the built-in php function array_search()
$key=array_search($yourId,$idsArray);
Hope this is what you are looking for.
On my models I try to write a php model that will get me a associative array from a database. But I don't quite know how to approach this.
So after I execute this SQL query:
SELECT balance_events.weight,balance_events.added_date,
balance_entries.mid FROM balance_events, balance_entries
WHERE balance_entries.added_date BETWEEN '2016-08-02' AND '2016-08-03'
AND balance_entries.ptid =12
AND balance_entries.beid = balance_events.id
I will get this table:
And from that table I want to extract a asociative array that it will look like this:
count = ['13'=>1, '6'=>4, '16'=>3, '4'=>3]
where 'mid'=>number of how many times that mid can be found in the table.
ex. mid '13'=>1 cause you can found it only once.
I think that I will have to use SQL COUNT function, but how I can aggregate all of this in a PHP model in codeigniter? I know how to configure controller and view, but I don't know how to actually do the actual php model that will get me the desired array.
Try this query may help you ,
$result = $this->db->select('balance_events.weight,balance_events.added_date,COUNT(balance_entries.mid) as mid_count')
->from('balance_events, balance_entries')
->where('balance_entries.added_date BETWEEN "2016-08-02" AND "2016-08-03" ')
->where('balance_entries.ptid','12')
->where('balance_entries.beid','balance_events.id')
->group_by('balance_entries.mid')
->get();
return $result->result_array();
I'm not sure how you would create this in SQL but since you tagged php, I wrote a function that would do just this.
<?php
$query = array(array("mid"=>13), array("mid"=>2), array("mid"=>13), array("mid" =>6), array("mid" => 13), array("mid" => 6));
function createMidArray($queryResult){
$returnArray = array();
foreach ($queryResult as $qr){
$returnArray[$qr['mid']]++;
}
return $returnArray;
}
print_r(createMidArray($query));
?>
The output of this was Array ( [13] => 3 [2] => 1 [6] => 2 ) which matches up to my inputted $query (which is a 2D array). I'm expecting the output of your query is stored in a similar array, but with more data and keys
Below I have stripped down my code to a simplified version. I am storing SQL SELECT results for:
last name (dlname)
category (category)
date this data was added to database (date_added)
clients name (client)
I have appended an additional field outside the SQL SELECT called 'days_on_list'. This field shows the number of days since the data was added to the database, making the table output 5 columns of user data. ALL 5 COLUMNS ARE TO BE SORTABLE.
I am using server-side JSON and have successfully been able to display this to the table and perform sorting on 4 of the 5 columns. The problem is that I am unable to sort the 'days_on_list' field as the PHP file containing the SQL code only allows me to sort the 4 fields from the select query. Is there a way I can make 'days_on_list' column be sortable in the table? I know I can add this field to the sql table, but I would have to run a scheduled event on the server to update this daily (which I am not comfortable with).
Is there another way to allow for this kind of flexible table sorting?
Sorry about the question title (may be confusing), I was having trouble putting this into a question.
/*SQL CODE ABOVE HERE STORES SELECT RETURNS IN $result*/
$cart = array();
$i = 0; //index the entries
// get variables from sql result.
if ($num_rows > 0) { //if table is populated...
while ($row = mysqli_fetch_assoc($result)) {
//calculate days on list by getting the number of days from
//the 'date_added' to today
$date1 = date_create($row['date_added']);
$today = date_create(date("d-m-Y"));
$interval = date_diff($date1, $today);
$doty = $interval - > format("%a");
$cart[$i] = array(
"dlname" => htmlspecialchars($row['dlname']),
"category" => htmlspecialchars($row['category']),
"date_added" => htmlspecialchars($row['date_added']),
"client" => htmlspecialchars($row['client']),
"days_on_list" => $doty, //date_added to now
);
$i = $i + 1; //add next row
}
//encoding the PHP array
$json_server_pagination_data = array(
"total" => intval($num_rows),
"rows" => $cart, //array data
);
}
echo json_encode($json_server_pagination_data);
Because days_on_list is calculated by simply comparing date_added to the current date, sorting by days_on_list should have exactly the reverse effect as sorting by date_added.
In other words, you don't actually need to sort by days_on_list. If the user selects days_on_list as the sort column, just use ORDER BY date_added (in the opposite direction ASC/DESC).
I have a findByAttributes in yii and I was wondering how you output all of the data that meets the criteria specified
I have an example below:
Assuming that in my Test table I have 3 rows which has the value 1 in test1 attribute then I have this code in my view
$a= Test::model()->findByAttributes(array('test1'=> '1'));
$b= $a-> id;
print_r($b);
I've noticed that this code would print the id '1' instead of '1 2 3'.
What code can I use so that it would output ALL of the ids with 1 in their test1 attribute?
sorry for the beginner question. I hope anyone can help...
If you want to get all records you have to use method findAllByAttributes (http://www.yiiframework.com/doc/api/1.1/CActiveRecord#findAllByAttributes-detail) instead of findByAttributes. Method findAllByAttributes will return all rows which meets requirements, then you should iterate over it to get an id.
Example,
foreach( $models as $model) {
print_r($model->id);
}
But if you want to get only ids it is better tou use CDbCommand and querycolumn
Yii::app()->db
->createCommand()
->select('id')
->from('Test')
->where('test1=:value', array(':value'=> 1))
->queryColumn()
It will return an array of ids
For retrive all the rows the meet a specific criteria you can use
findAllByAttributes();
And for obtain all the result you must loop eg ever this result:
$a= Test::model()->findAllByAttributes(array('test1'=> '1'));
foreach($a as $key => $value) {
echo $value->id
}
i am trying to covert this query in active record
SELECT
crm_clients.id,
crm_clients.`moved_date`,
crm_clients.`contractor_id`
FROM
dev_pfands.`crm_clients`
WHERE crm_clients.`contractor_id` = 11
AND (
crm_clients.`status` = 9
OR crm_clients.`status` = 8
OR crm_clients.`status` = 7
)
AND crm_clients.id IN
(SELECT
crm_client_cheques.`client_id`
FROM
dev_pfands.`crm_client_cheques`)
AND crm_clients.`moved_date` BETWEEN '2014-08-01'
AND '2014-11-29 '
AND crm_clients.`contractor_id`<>''
GROUP BY crm_clients.`id
the section I'm having issue is
AND crm_clients.id IN
(SELECT
crm_client_cheques.client_id
FROM
dev_pfands.crm_client_cheques) `
i've tried the where_in method but overtime i try to include my attempt of $this ->db_pfands -> where('crm_client_cheques.client id' ,'id'); get hit with errors and have no idea how to get past this.
the original query should return 703 rows and when I've removed the part I'm stuck with it increase to 3045 so i need it to be included. any help is appreciated.
First of all you have a error in your code.
$this->db_pfands->where('crm_client_cheques.client id', 'id');
This will be
$this->db_pfands->where('crm_client_cheques.client_id', 'id');
You have to provide the right column name and as far i know database's column name have not contain any space.
Now I think this active record query will help you to get your result.
$query = $this->db->select('crm_clients.id, crm_clients.moved_date, crm_clients.contractor_id')
->where('moved_date BETWEEN "2014-08-01" AND "2014-11-29"')
->where('contractor_id', 'id')
->where_in('status', [9,8,7])
->from('crm_clients')
->join('crm_client_cheques', 'crm_client_cheques.client_id = crm_clients.id')
->group_by('id')
->get();
$result = $query->result();
May be you have change couple of names because they are in different database, but i believe you can do it.