CakePhp getting the number of entries of each code - php

I want to do a search of data and get the number of entries it has on another table
$query = $this->find();
$query->select([
'name',
'code',
'count' => "(
SELECT
COUNT(products_branches.id)
FROM
products_branches
INNER JOIN
branches
ON branches.company_id = products_branches.company_id
AND branches.code = products_branches.branch_code
WHERE
products_branches.deleted = 0
AND products_branches.carried = 1
AND products_branches.company_id = $company_id
AND products_branches.branch_code = code
)",
]);
is there a way that I could use the code fetch in the select and use at as one of the condition in the search condition of the subquery?
I want to search the number of entries each name and code has on product_branches table

What you're looking to do is possible, but you've got a few more steps to complete. You need to make sure you create an Association between the products_branches and branches table first. Then you can use the where() function to do what you want to do. Something like this:
$q = $this-find('all')
->select(['Branches.name', 'Branches.code'])
->contain(['ProductsBranches'])
->where(['ProductsBranches.deleted' => 0,
'ProductsBranches.carried' => 1,
'ProductsBranches.company_id' => $company_id,
'ProductsBranches.branch_code' => $code]);
$count = $q->all()->count();

Related

Cakephp 3 Sum 2 columns of same table

How to Sum two columns of the same table in CakePhp 3 ?
lets say i want to sum the values of two columns i.e stitching_amount and item_amount of table order_details .. So how can I do this ?
I have tried this piece of code for this but it is not working in Cakephp 3.8 ..
$query = $this->OrderDetails->find();
$query
->select([
'val' => $query
->newExpr()
->add($query->func()->sum(
new IdentifierExpression('OrderDetails.item_amount')
))
->add($query->func()->sum(
new IdentifierExpression('OrderDetails.stitching_amount')
))
->tieWith('+')
])
->where(['order_id' => $lastorderid]);
Whereas I have done this in corephp and its working perfectly, I want to do this in Cakephp3, like this
SELECT
SUM(stitching_amount+item_amount) AS Total
FROM
order_details
WHERE
id=" . $run_orders['id'];
Try this:
$query->select([
'Total' => $query->func()->sum($query->newExpr('OrderDetails.item_amount + OrderDetails.stitching_amount'))
]);

Elgg: Is it possible to Order an array by a separate variables order_by

So, I have been looking around and working with Elgg 1.8 for quite some time now, and while I am getting the hang of it, I am still a complete novice.
I have had this idea to sort my table which grabs certain information from elgg itself, specifically the groups and such. I want to sort everything by its tabs (name, total, difference, date) and for name and date elgg has been rather straight forward with that. However, I am not quite sure if I can do the same with the total and difference because of that. Take note of the code below.
$GroupArray = elgg_get_entities(array(
'type' => 'group',
//try to get this to use the order of the totalmembers
'order_by' => $Order . " " . $Sort,
'joins' => 'JOIN ' . $db_prefix . 'groups_entity ge',
'limit' => 10,
'pagination' => true,
'offset' => $Offset,
));
This $GroupArray captures all of the group stats which allows me to add all of the necessary information into the table, and the $Order and $Sort variables are dynamically added by clicking on the tabs in the table. Name and Date are already initialized in elgg with ge.name and e.time_created, but I need to do some trickery to get the members and total working the same way.
$TotalMembers = elgg_get_entities_from_relationship(array(
'relationship' => 'member',
'relationship_guid' => $Reports->guid,
'inverse_relationship' => true,
'type' => 'user',
'limit' => 20,
'joins' => array("JOIN {$db_prefix}users_entity u ON e.guid=u.guid"),
'order_by' => 'u.name ASC',
'count' => true,
'relationship_created_time_lower'
));
This is how I get the total amount of members for each column and group, it comes after the group array as that is what allows it to be grabbed. My issue now is trying to that the $TotalMembers 'order_by' to be put into the $Order variable, essentially sorting by the min to max total members for each group.
I have searched far and wide to no avail, and im not sure if my idea is plausible or if it even works as I think it can.
Is anyone able to give me a push in the right direction?
Well, it turns out it is possible, you just need to take apart Elgg's code and replace it with the Sql would otherwise create for you
$allQuery =
"SELECT DISTINCT e.guid, ge.name,
(SELECT count(DISTINCT e.guid)
FROM elgg_entities e
JOIN elgg_users_entity u
ON e.guid=u.guid
JOIN elgg_entity_relationships r
on r.guid_one = e.guid
WHERE (r.relationship = 'member'
AND r.time_created >=1507476424
AND r.guid_two = ge.guid)
AND ((e.type = 'user'))
AND (e.site_guid IN (1))
AND ( (1 = 1) and e.enabled='yes')) as totalMembers
FROM elgg_entities e JOIN elgg_groups_entity ge
ON e.guid=ge.guid
WHERE ((e.type = 'group'))
AND (e.site_guid IN (1))
AND ( (1 = 1) and e.enabled='yes')
ORDER BY totalMembers $Sort
LIMIT $Offset, 10";
$allData = get_data($allQuery);
This just takes the two different elgg statements which are really sql statements and joins them together so that it is now possible to search by the max avaliable for the total members query.

SUM row field MEDOO

I am trying to get a summed field in medoo.
My sql at the moment is like:
$database->debug()->select("user_rupees_in_house", [
"[<]rupees" => ["rupee_id" => "ID"]
], [
"name",
"amount",
"amount_spend"
], [
"user_uuid" => $user,
"GROUP" => "rupee_id"
]);
The debug logs the following statement:
SELECT `name`,`amount`,`amount_spend`, `rupee_id`
FROM `user_rupees_in_house`
RIGHT JOIN `rupees`
ON `user_rupees_in_house`.`rupee_id` = `rupees`.`ID`
WHERE `user_uuid` = '4da9ff11-56ca3a2f-b3ab-a25b9230'
GROUP BY `rupee_id`
What I'm trying to achieve is:
SELECT `name`,SUM(`amount`),SUM(`amount_spend`), `rupee_id`
FROM `user_rupees_in_house`
RIGHT JOIN `rupees`
ON `user_rupees_in_house`.`rupee_id` = `rupees`.`ID`
WHERE `user_uuid` = '4da9ff11-56ca3a2f-b3ab-a25b9230'
GROUP BY `rupee_id`
Does anybody know how to make this statement in medoo?
[EDIT 1]
Found another way of achieving this
// Get the rupee types
$rupee_types = $database->select("rupees", "ID");
foreach ($rupee_types as $rupee_type) {
$amount = $database->sum("user_rupees_in_house", "amount", [
"AND" => [
"rupee_id" => $rupee_type,
"user_uuid" => $user
]
]);
// Build array of rupees
}
This will make a lot more calls to the database, but is working just fine as long as the SELECT statement does not support aggregate functions.
Medoo doesn't support aggregate function in SELECT statement. Use raw query instead.
Try this:
$result = $database->query(
"SELECT `name`,SUM(`amount`),SUM(`amount_spend`), `rupee_id`
FROM `user_rupees_in_house`
RIGHT JOIN `rupees`
ON `user_rupees_in_house`.`rupee_id` = `rupees`.`ID`
WHERE `user_uuid` = '$user'
GROUP BY `rupee_id`"
)->fetchAll();
Reference

Filtering HABTM with AND Condition

I'm trying to filter some car parts depending on the categories they are related to.
A part can have many categories (in the code they are called tags), so I chose the HABTM relation with a join table.
Filtering works so far, but only with an OR condition with cake using the SQL command IN.
But I'm trying to filter only the parts that have all the selected categories, so I need to use an AND condition on the category array.
Here's the extracted code from the controller:
$this->Part->bindModel(array('hasOne' => array('PartsTagsJoin')));
$params['conditions'] = array('AND' => array('PartsTagsJoin.tag_id' => $selectedCats));
$params['group'] = array('Part.id');
$parts = $this->Part->find('all',$params);
$this->set('parts',$parts);
$selectedCats is an array like this: array(1,2,3,4,5);
The SQL output is:
'SELECT `Part`.`id`, `Part`.`name`, `Part`.`image`, `Part`.`image_dir`, `Part`.`time_created`, `Part`.`time_edited`, `Part`.`user_id`, `Part`.`editor_id`, `Part`.`notice`, `User`.`id`, `User`.`username`, `User`.`password`, `User`.`usergroup_id`, `User`.`realname`, `PartsTagsJoin`.`id`, `PartsTagsJoin`.`part_id`, `PartsTagsJoin`.`tag_id`
FROM `c33rdfloor`.`parts` AS `Part`
LEFT JOIN `c33rdfloor`.`users` AS `User` ON (`Part`.`user_id` = `User`.`id`)
LEFT JOIN `c33rdfloor`.`parts_tags_join` AS `PartsTagsJoin` ON (`PartsTagsJoin`.`part_id` = `Part`.`id`)
WHERE `PartsTagsJoin`.`tag_id` IN (1, 4, 8, 24)'
How can I filter the parts that have every id that is committed through the $selectedCats Array.
Thank you in advance for your help.
I've got it working thanks to this blog post:
http://nuts-and-bolts-of-cakephp.com/2008/08/06/habtm-and-join-trickery-with-cakephp/
It seems to be a little tricky to filter entries with all selected tags:
The key in achieving an AND relation is to get the count of the selected cats and match it with the ones of the query inside the group parameter.
This line did it:
$params['group'] = array('Part.id','Part.name HAVING COUNT(*) = '.$numCount);
In the End the code looked like this (for people interested in a solution):
// Unbinds the old hasAndBelongsToMany relation and adds a new relation for the output
$this->Part->unbindModel(array('hasAndBelongsToMany'=>array('PartsTag')));
$this->Part->bindModel(array('hasOne'=>array(
'PartsTagsJoin'=>array(
'foreignKey'=>false,
'type'=>'INNER',
'conditions'=>array('PartsTagsJoin.part_id = Part.id')
),
'PartsTag'=>array(
'foreignKey'=>false,
'type'=>'INNER',
'conditions'=>array(
'PartsTag.id = PartsTagsJoin.tag_id',
'PartsTag.id'=>$selectedCats
)))));
$numCount = count($selectedCats); // count of the selected tags
// groups the entries to the ones that got at least the count of the selected tags -> here the 'AND' magic happens
$params['group'] = array('Part.id','Part.name HAVING COUNT(*) = '.$numCount);
$parts = $this->Part->find('all', $params); // sends the query with the params
$this->set('tagCategories', $categories);
$this->set('selectedCats', $selectedCats);
$this->Part->recursive = 4;
$this->set('parts',$parts);

CakePHP pagination with HABTM models

I'm having some problems with creating pagination with a HABTM relationship. First, the tables and relationships:
requests (id, to_location_id, from_location_id)
locations (id, name)
items_locations (id, item_id, location_id)
items (id, name)
So, a Request has a Location the request is coming from and a Location the Request is going to. For this question, I'm only concerned about the "to" location.
Request --belongsTo--> Location* --hasAndBelongsToMany--> Item
(* as "ToLocation")
In my RequestController, I want to paginate all the Items in a Request's ToLocation.
// RequestsController
var $paginate = array(
'Item' => array(
'limit' => 5,
'contain' => array(
"Location"
)
)
);
// RequestController::add()
$locationId = 21;
$items = $this->paginate('Item', array(
"Location.id" => $locationId
));
And this is failing, because it is generating this SQL:
SELECT COUNT(*) AS count FROM items Item WHERE Location.id = 21
I can't figure out how to make it actually use the "contain" argument of $paginate...
Any ideas?
after 3 days searching, I found the way
var $paginate = array('Post'=>array('group'=>'Post.id'));
It's recomended to add group, because sometimes we will get duplicte posts in different categories
$this->Post->bindModel(array('hasOne'=>array('CategoriesPost')), false);
$out = $this->paginate('Post', array('CategoriesPost.category_id'=>array(1,4,7,6)));
Add false to use bind model to all queries, not only to the following
To paginate HABTM, you need to temporarily bind 'hasOne' join model to model which you paginate:
// prepare to paginate Item
$this->Item->bindModel(array('hasOne'=>array('ItemsLocation')));
$contain['ItemsLocation']=array();
$conditions[]=array('ItemsLocation.location_id'=>$locationId);
$order = array('Item.created' => 'desc'); // set order
...
$items = $this->paginate('Item', compact('conditions','contain','order'));
I've been able to get it working somewhat, but the solution doesn't feel very cakey at all.
$items = $this->paginate(
$this->Request->ToLocation->Item,
array(
"Item.id IN ("
. "SELECT item_id FROM items_locations "
. "WHERE location_id = " . $locationId
. ")"
)
);

Categories