Laravel orWhereIn and orWhereIn and so on - mysql

To be honest I rly do not know how to describe my query problem, hope example will clear things up:
I've got simple query:
return $query->whereHas('categories', function ($q) use ($ids) {
$q->whereIn('category_id', $ids);
}, '=', count($ids));
which returns records that match array of categories ids. To present this better right now we've got such condition
getRecordsThatMatchThisCondition(id1 && id2 && id3... and so on).
What I want is to achieve such comparasion
getRecordsThatMatchThisCondition((id1.1 || id1.2 || id1.3) && (id2.1 || id2.2) ... and so on.)
I've couldn't find any help with this problem so far. Even naming such query would be helpfull. My table is simple PIVOT
id record_id category_id
------------------------------------
1 1 35
2 2 41
3 2 74
4 3 74
5 3 40
6 4 40
Summarizing my problem with words:
I do not have record relation to parent_category of selected category... Right now I need to display all records that match multiple categories.
Visualising problem:
Record is assigned to categories like this:
35
└40
└41 ☑
36
└74 ☑
By providing id 35 and 36, record should be found! By providing 40, 74 should NOT be found...
Hope I've described my problem well enough.

You can't query with whereIn method like this, but can use a foreach loop, like this :
return $query->whereHas('categories', function ($q) use ($ids) {
foreach($ids as $key => $value) {
$q->orWhere('category_id', $value)
}
}, '=', count($ids));
Or, with for loop :
return $query->whereHas('categories', function ($q) use ($ids) {
for ($i = 0; $i < count($ids); $i++){
$q->orWhere('category_id', $ids[$i]);
}
}, '=', count($ids));

Related

How to query in EF core with OrderByDescending, Take, Select and FirstOrDefault

So I've got a table named Summaries, it looks like this
I need to get to sum the latest entries of TotalPieces based on CoveredDate and should be grouped by ServiceCode and queried by month
for example, ServiceCode 'A' has entries on 2020-01-01, 2020-01-02, 2020-01-03, 2020-01-31, 2020-02-01, 2020-02-28, 2020-02-29
and ServiceCode 'B' has entries on 2020-01-01, 2020-01-02, 2020-01-31, 2020-02-20, 2020-02-21,
i need to get the sum based on month, lastest entry on 'A' on January is on 2020-01-31, and 'B' has latest entry on 2020-01-31, I need to sum their 'TotalPieces', so I should get 25 + 25 = 50.
basically i need to do is
Get all the lastest entries based on CoveredDate and month/year
Sum the TotalPieces by ServiceCode
i got a working query, but this is just a workaround because i can't get it right on query.
int sum_totalpieces = 0;
foreach (var serviceCode in service_codes)
{
var totalpieces = _DbContext.ActiveSummaries.Where(acs =>
acs.CoveredDate.Date.Month == query_month
&& acs.CoveredDate.Date.Year == query_year
&& acs.service_codes == serviceCode
)
.OrderByDescending(obd => obd.CoveredDate)
.Take(1)
.Select(s => s.TotalPieces)
.ToList()
.FirstOrDefault();
sum_totalpieces += totalpieces;
}
the service_codes is just a List of string
If you guys could just get rid of the foreach block their and make it services_codes.Contains() on query, or another workaround to make the result faster that would be great. Thanks a lot.
This will do it, but I don't think it will translate to SQL and run at the server:
_DbContext.ActiveSummaries
.Where(b =>
b.CoveredDate >= new DateTime(2020,1,1) &&
b.CoveredDate < new DateTime(2020,2,1) &&
new [] { "A", "B" }.Contains(b.ServiceCode)
)
.GroupBy(g => g.ServiceCode)
.Sum(g => g.OrderByDescending(gb=> gb.CoveredDate).First().TotalPieces);
If you want to do it as a raw SQL for best performance it would look like:
SELECT SUM(totalpieces)
FROM
x
INNER JOIN
(
SELECT servicecode, MAX(covereddate) cd
FROM x
WHERE x.servicecode IN ('A','B') AND covereddate BETWEEN '2020-01-01' AND '2020-01-31'
)y ON x.servicecode=y.servicecode and x.covereddate = y.cd

How do I count multiple columns with a vertical value?

I'm new to programing. I have table
check_1,check_2,check_3 ..etc
------------------------------
1 1 1
0 0 1
1 0 1
And I want this output :
column_name, count_true
-----------------------
check_1 2
check_2 1
check_3 3
I've tried it with mysql using the union function, but when I try to apply it in laravel I have trouble with union. Is there a unionless query that can produce such output?
Thanks in advance
You can do this way. One query in db
$records = DB::table('your_table')->get();
$check1Count = $records->where('check_1', 1)->count();
$check2Count = $records->where('check_2', 1)->count();
$check3Count = $records->where('check_3', 1)->count();
......
Or
$records = DB::table('your_table')->get();
$columns = ['check_1', 'check_2', 'check_3', ...];
$data = [];
foreach($columns as $column) {
$data[] = [
'column_name' => $column,
'count_true' => $records->where($column, 1)->count();
];
}
Also you can do this way but it is many query
$check1Count = DB::table('your_table')
->selectRaw('COUNT(check_1) as count')
->where('check_1', 1)
->first()
->count;
$check2Count = DB::table('your_table')
->selectRaw('COUNT(check_2) as count')
->where('check_2', 1)
->first()
->count;
.....
A normalised approach might look like this:
response_id checkbox
1 1
1 2
1 3
2 3
3 1
3 3
You don't need union, just query all the data and process it on Laravel. Let say you query all the data using eloquent to $data variable, then you should do it like this:
//preparing a variable to hold all 24 database field value
$total = [];
foreach ($data as $d) {
//do this for all 24 database field
if ($d->check_1) {
$total[1]++;
}
if ($d->check_2) {
$total[2]++;
}
...
}
By using that way you can't check the resutl on $total[index] variable. And yes, there is a better way to store your data instead of saving all the field for each user. You can just store all checked value in database that look like this :
user_id checkbox_id
1 3
1 5
1 9
1 24
2 23
3 2
3 3
It more efficient since you don't need to save the unchecked checkbox value, if they more likely not to checked most of the checkbox.

How to get the all child rows recursively using CodeIgniter and MySQL?

How to get the all child rows and their child rows using CodeIgniter and MySQL?
Here is the Table structure
Id user_id sponser_id
1 1 0
2 2 1
3 3 1
4 4 1
5 5 2
6 6 2
7 7 2
8 8 3
9 8 3
10 10 4
I want to get all the child row which is connected under particular sponser_id. I have trid this query but I can't get proper detail.
$this->db->select('u_fname,u_lname,sponsor_id');
$this->db->from('user_reg');
$this->db->where('sponsor_id', $user_data['otc_id']);
$query = $this->db->get();
Here is the graphical representation of what i am doing. I want all children row of A and same as b to O.
I am calling this function from my controller to get the desired output.
Controller Code:
public function index()
{
$all_level_array = array();
$user_data = $this->common->user_data_db();
$get_user_level = $this->u_buildup_wallet_model->get_user_buildup_level($user_data['otc_id']);
if(!empty($get_user_level)){
foreach ($get_user_level as $userData) {
$test = $this->u_buildup_wallet_model->get_user_buildup_level($userData['otc_id']);
print_r($test);
}
}
print_r($all_level_array);
exit
$this->load->view();
}
Model Code:
public function get_user_buildup_level($user_otc)
{
$this->db->select('u_fname,u_lname,sponsor_id,otc_id');
$this->db->from('user_reg');
$this->db->where('sponsor_id', $user_otc);
$query = $this->db->get();
$result = $query->result_array();
return $result;

Yii2 Find all products in parent category

I have 2 tables structure as following:
category(id,cat_name , parent_id);
product(id,category_id ,pro_name);
Relation in Product Model
public function getCategory()
{
return $this->hasOne(Category::className(), ['id' => 'category_id']);
}
Category
id cat_name parent_id
1 Electronic 0
2 Fruit 0
3 TV 1
4 Apple 2
Product
id category_id pro_name
1 1 Samsung
2 3 Sony
3 3 Panasonic
4 2 Apple
5 2 Orange
What I want to do is when I select on category (1) Electronic
I want to get
Samsung,Sony,Panasonic from table Product
So, you must have a relational function in your Category model calling more Categories. And another relational function calling the Products. I'm assuming the names are getParentId() and getProducts(). (If you dont have, you can use Gii to generate them for you)
Here is a recursive approach you can do inside your Category model:
public function getSubCategories()
{
if ($categories = $this->parentId) { // the name of your relational function.
foreach ($this->parentId as $sub) {
$categories = array_merge($categories, $sub->subCategories);
}
}
return $categories;
}
public function getProductsWithSubcategories()
{
$products = $this->products; // the name of your relational function.
foreach ($this->subCategories as $sub) {
$products = array_merge($products, $sub->products);
}
return $products;
}
// given $id is your current toplevel category
$cat_ids = Category::find()->select('id')->where(['parent_id' => $id])->asArray()->all();
$ids = [];
foreach($cat_ids as $value)
{
$ids[] = $value['id'];
}
$ids = implode(',',$ids);
$categories = Products::find()->where('category_id IN ('.$ids.','.$id.')')->all();
Some object to array functionallity there that you might be able to clean up. This was quick and dirty, but should work. You get the point.

Codeigniter : retrieve lastest row in table?

table name : mytable
id name salt value
1 a 10 39
2 a 20 13
3 a 10 14
4 b 40 39
mymodel.php
function get_value_by_name($name)
{
$this->db->select("*");
$this->db->from("mytable");
$this->db->where('salt', '10');
$this->db->where('name', $name);
$this->db->order_by('id',"ASC");
$this->db->limit(1);
$query=$this->db->get();
if($query != null){
return $query->result();
}
else{
return array();
}
}
I want to get latest row with name= a and salt=10 (row with id = 3). But my current code return 1st row.
Change
$this->db->order_by('id',"ASC");
By
$this->db->order_by('id',"DESC");