How to achieve this query in phalcon using query builder (best method):
$results = "select * from table where name like 'A%' limit 10"; // <-- 10 records
$total = "select count(1) from table where name like 'A%'"; // <-- 100 records
return [
'data' => $result,
'total' => $total
];
im extjs user and i need to get total over limit to display paging information (eq: displaying 1 to 10 from 100 records)
thx.
You can achieve this with Pagination, see here: Pagination Docs
Only thing is to use QueryBuilder adapter. But this can be done with:
$builder = $this->modelsManager->createBuilder()
->from('Table')
->andWhere('name like :name:', array('name' => 'A%' ) );
$paginator = new Phalcon\Paginator\Adapter\QueryBuilder(array(
"builder" => $builder,
"limit"=> 10,
"page" => 1
));
return [
'data' => $paginator->items,
'total' => $paginator->total_items
];
Related
How can I get data by grouping user_id for a foreach loop in a controller's function in Laravel. For example, user_id = 2, 5 rows available, user_id = 1, 10 rows available. Then show 2 arrays.
$lists = lists::wherestatus(1)->groupby('user_id')->get();
foreach($lists as $list){
$list = functionHere;
}
What function can I create for this on the controller for grouping?
I need more information, but based on what you shared, you should be able to do this (removing the foreach):
$lists = Lists::whereStatus(1)->get()->groupBy('user_id');
The difference is that if you use groupBy before get, you are grouping your query by user_id, so instead of getting 5 rows for user_id = 2 and 10 for user_id = 1, you are going to get 2 rows and just the latest data, so you need to use Collection's groupBy.
What you want to do is group all the information by user_id but have each row, a schema like this:
[
'1' => [ // user_id
['user_id' => '1', 'column1' => 'random value'],
['user_id' => '1', 'column1' => 'other value'],
// 8 remaining rows
],
'2' => [ // user_id
['user_id' => '2', 'column1' => 'other nice value'],
// 4 remaining rows
],
]
you should first in List model set:
public function scopeStatus(){
return $this->where('status','1');
}
and in your controller:
$products = List::status()->groupby('user_id')->get();
I need to paginate the data I fetch from my BigTable instance. I've tried applying filters and maxResults option but it fetches all the rows within the set range. Can I limit the read query to fetch last n records somehow?
I've tried following:
$bigtable = new BigtableClient($config);
$table = $bigtable->table('engage', 'engage_dataplatform_' . ceil((int)$store->id / 10000.0));
$filter = Filter::chain()
->addFilter(Filter::limit()->cellsPerColumn(1))
->addFilter(Filter::qualifier()->regex("(product_id|name|image_type|link|image|price|status|product_type|sku|average_rating|product_cost)"));
$rows = $table->readRows([
'filter' => $filter,
'rowRanges' => [
[
'startKeyClosed' => 'products#'.$store->id.'#',
'endKeyOpen' => 'products#'.((int)$store->id+1).'#'
],
],
'maxResults' => 10,
'startIndex' => 0,
]);
I am trying to LIMIT a Query which is already been selected. I know I can directly do it in my query select, but due to some logics of the code, if I do that way I have to run the query selection twice which (I believe) will increase the computational time!
So, what I am trying is this:
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions");
then, I need to re-select a sub-selection of the $query1 for my Pagination. What I am trying to do is something like this;
$query2 = LIMIT($query1, $limit_bigin, $limit_end);
where $limit_bigin, $limit_end provide the LIMITING range (start and end respectively).
Could someone please let me know how I could do this?
P.S. I know I can do it directly by:
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions");
$query2 = $mysqli->query("SELECT * FROM tableName WHERE someConditions LIMIT $limit_bigin, $limit_end");
But this is running the query twice and slows down the process (I must run the first query without limits due to some logics of the program)
EDIT 1
As per the answers I tried using array_slice in PHP. BUT, since Query is an object it doesn't give the results that was expected. A NULL is resulted form
array_slice($query1, $start, $length, FALSE)
If you have already carried out the query and the result set has been returned to your PHP, you can not then LIMIT it. As you state, then running a second SQL execution of a subpart of the same query is wasteful and repetative.
Don't
Repeat
Yourself.
DRY.
As I said above, repetition causes issues with maintainability as you can easily forget about repetition, tweaking one SQL and forgetting to tweak the other.
Don't
Repeat
Yourself.
DRY.
Use PHP instead
Once you have executed the query, the result set is then passed back to PHP.
So assuming you have a $var with the contents of you SQL query, then you simply need to select the valid rows from the $var, not from the database [again].
You can do this using PHP numerous Array functions. Particularly array_slice().
So;
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions");
Now, to select the second page, say for example rows 10 to 20:
$query2 = array_slice($query1, (10-1), 10 );
This wil then "slice" the part of the array you want. Remember that the array counts will start at zero so to grab row 10 (of an index starting at 1, Typical of a MySQL Auto Increment Primary Key), then you will need to select X number of rows from row (10-1) .
Please also read the manual for PHP array_slice().
Further
As referenced in comments, there is no guarentee that your SQL will return the same values each time in the same order, so it is highly recommended to order your results:
$query1 = $mysqli->query("SELECT * FROM tableName
WHERE someconditions ORDER BY primary_key_column");
Example Data:
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions ORDER BY id");
/***
$query1 = array {
0 => array { 'id' => 1, 'user' => "Jim", 'colour' => "Blue" },
1 => array { 'id' => 2, 'user' => "Bob", 'colour' => "Green" },
2 => array { 'id' => 3, 'user' => "Tom", 'colour' => "Orange" },
3 => array { 'id' => 4, 'user' => "Tim", 'colour' => "Yellow" },
4 => array { 'id' => 5, 'user' => "Lee", 'colour' => "Red" },
5 => array { 'id' => 6, 'user' => "Amy", 'colour' => "Black" }
}
***/
$page = 2;
$size = 3; // number per page.
$start = ($page - 1) * $size; //page number x number per page.
// Select the second page of 3 results.
$query2 = array_slice($query1, $start, $size , FALSE);
/***
$query2 = array {
0 => array { 'id' => 4, 'user' => "Tim", 'colour' => "Yellow" },
1 => array { 'id' => 5, 'user' => "Lee", 'colour' => "Red" },
2 => array { 'id' => 6, 'user' => "Amy", 'colour' => "Black" }
}
***/
You can then use these in a foreach or other standard array manipulation technique.
Is it possible to use subquery when updating an ActiveRecord?
I have a products table with following columns
id number_of_orders
1 3
2 3
3 2
and an items table
id product_id
1 1
2 1
3 1
4 2
5 2
6 2
7 3
8 3
What I want is
UPDATE products
SET number_of_orders = (
SELECT COUNT(id) FROM items WHERE product_id = 1
)
WHERE id = 1
I have tried
$subquery = ItemsModel::find()
->select('COUNT(id)')
->where(['product_id' => 1]);
ProductsModel::updateAll(
[
'number_of_orders' => $subquery
],
[
'id' => 1
]
);
and
$product = ProductsModel::findOne(1);
$product->number_of_orders = $subquery;
$product->save();
but none of this going to work.
Does anyone have any idea about solving this problem?
Conclusion:
Each of the two ways works very well after I updated to yii 2.0.14.
Try update Yii to the last version. Since 2.0.14 all instances of yii\db\ExpressionInterface (including Query and ActiveQuery) should be handled properly and generate SQL in similar way as yii\db\Expression. So all this should work in Yii 2.0.14 or later:
$subquery = ItemsModel::find()
->select('COUNT(id)')
->where(['product_id' => 1])
ProductsModel::updateAll(
['number_of_orders' => $subquery],
['id' => 1]
);
$product = ProductsModel::findOne(1);
$product->number_of_orders = $subquery;
$product->save();
ProductsModel::updateAll(
['number_of_orders' => new Expression('SELECT COUNT(id) FROM items WHERE product_id = 1')],
['id' => 1]
);
Last example should work also in earlier versions of Yii.
You can use count() to get number of records.
$itemCount = ItemsModel::find()
->where(['product_id' => 1]);
->count();
$product = ProductsModel::findOne(1);
$product->number_of_orders = $itemCount;
$product->save();
i would prefer:
$model = ProductsModel::findOne(1);
$model->updateAttributes(['number_of_orders' => ItemsModel::find()->where(['product_id' => 1])->count()]);
or you can do
$query = Yii::$app->db
->createCommand(sprintf('UPDATE %s SET number_of_orders=(SELECT COUNT(*) FROM %s WHERE product_id=:id) WHERE id=:id', ProductsModel::tableName(), ItemsModel::tableName()), [':id' => $id, ])
->execute();
ps: if both tables are the same, you have to do:
$query = Yii::$app->db
->createCommand(sprintf('UPDATE %s SET number_of_orders=(SELECT * FROM (SELECT COUNT(*) FROM %s WHERE product_id=:id) xxx) WHERE id=:id', ProductsModel::tableName(), ItemsModel::tableName()), [':id' => $id, ])
->execute();
Hi i am using CakePHP version - 2.5.5.
I have a table name chat_ategory_mages I want to get Average number of Frequency Order by Descending. Know about the Frequency please check - How to get Average hits between current date to posted date in MySQL?
chat_ategory_mages
id chat_category_id hits created
------------------------------------------------
1 5 10 2014-11-07 11:07:57
2 5 8 2014-11-10 05:10:20
3 5 70 2014-10-04 08:04:22
Code
$order=array('Frequency' => 'DESC');
$fields=array(
'ChatCategoryImage.id',
'ChatCategoryImage.chat_category_id',
'ChatCategoryImage.created',
'ChatCategoryImage.hits',
'hits/(DATEDIFF(NOW(),created)) AS Frequency',
);
QUERY-1
$rndQry=$this->ChatCategoryImage->find('all',array('conditions'=>array('ChatCategoryImage.chat_category_id'=>$cetegory_id), 'fields'=>$fields, 'order'=>$order, 'limit'=>10));
pr($rndQry); //WORKING FINE
QUERY-2
//THIS IS NOT WORKING
$this->Paginator->settings = array(
'conditions'=>array('ChatCategoryImage.chat_category_id'=>$cetegory_id),
'fields'=>$fields,
'limit' => 10,
'order' => $order,
);
$getCategoryImages = $this->Paginator->paginate('ChatCategoryImage');
pr($getCategoryImages); //NOT WORKING
Above table if i write simple cakephp query the order is working fine but when i am using cakephp pagination it is not working. If i am using $order=array('hits' => 'DESC'); this its woring perfect. Showing result 70,10,8 consistently but when i am adding Frequency it the result not coming the descending order.
Mysql Query
QUERY-1 :
SELECT ChatCategoryImage.id, ChatCategoryImage.chat_category_id, ChatCategoryImage.hits, ChatCategoryImage.created, hits/(DATEDIFF(NOW(),created)) AS Frequency, FROM myshowcam.chat_category_images AS ChatCategoryImage WHERE ChatCategoryImage.chat_category_id = 5 ORDER BY Frequency DESC LIMIT 10
QUERY-2 :
SELECT ChatCategoryImage.id, ChatCategoryImage.chat_category_id, ChatCategoryImage.hits, ChatCategoryImage.created, hits/(DATEDIFF(NOW(),created)) AS Frequency, FROM myshowcam.chat_category_images AS ChatCategoryImage WHERE ChatCategoryImage.chat_category_id = 5 LIMIT 10
What is the problem and why its not coming ORDER BY Frequency in the second query?
Thanks
chinu
You can use virtualFields
$this->ChatCategoryImage->virtualFields = array('Frequency' => 'hits/(DATEDIFF(NOW(),created))');
changing the way of order
$order = array('Frequency' => 'desc');
This happened to me to. You have to add to the paginate function the third parameter $whitelist. For example.
$this->Paginator->settings = array(
'conditions'=>array('ChatCategoryImage.chat_category_id'=>$cetegory_id),
'fields'=>$fields,
'limit' => 10,
'order' => $order,
);
$scope = array();
$whitelist = array('ChatCategoryImage.id', ...); //The fields you want to allow ordering.
$getCategoryImages = $this->Paginator->paginate('ChatCategoryImage', $scope, $whitelist);
pr($getCategoryImages);
I do not know why this is happening. I tried to see the code inside the paginate function but i could not figure it out.
Your code was lil wrong
$this->paginate = array(
'conditions' => array('ChatCategoryImage.chat_category_id'=>$cetegory_id),
'limit' => 10, 'order' => 'Frequency' => 'DESC');
$getAllCourses = $this->paginate('ChatCategoryImage');