Update one Table Using another Table Record - mysql

I have two tables as follows that joined by budget_id.
finance_budget table
+-----------+--------+------------+-----------------+---------------+
| budget_id | amount | date | transfer_status | budget_status |
+-----------+--------+------------+-----------------+---------------+
| 1 | 135000 | 2019-10-01 | Pending | issue |
| 2 | 25000 | 2019-10-02 | Pending | issue |
| 3 | 234000 | 2019-10-03 | Pending | issue |
| 4 | 175000 | 2019-10-03 | Pending | issue |
+-----------+--------+------------+-----------------+---------------+
finance_budget_issue table
+----+-----------+-----------+--------+-----------------+---------------+
| id | budget_id | office_id | amount | transfer_status | budget_status |
+----+-----------+-----------+--------+-----------------+---------------+
| 1 | 1 | 100 | 135000 | Pending | issue |
| 2 | 2 | 101 | 12500 | Pending | issue |
| 3 | 2 | 102 | 12500 | Pending | issue |
| 4 | 3 | 100 | 100000 | Pending | issue |
| 5 | 3 | 105 | 75000 | Pending | issue |
| 6 | 3 | 104 | 59000 | Pending | issue |
| 7 | 4 | 102 | 125000 | Pending | issue |
| 8 | 4 | 110 | 50000 | Pending | issue |
+----+-----------+-----------+--------+-----------------+---------------+
I tried to change the "transfer_status" of above two tables from "Pending" to "Approved" using my model
Controller
public function approveIssues($id){
$this->checkPermissions('index', 'pendingIssues');
if(empty($id)){
redirect('budget/pendingIssue');
}
if($this->Budget_model->approveIssues($id)){
$this->session->set_flashdata('message', 'Allocation Approved successfully ..!!');
redirect('budget/pendingIssue');
}else{
$this->session->set_flashdata('error', 'Error ...!!!');
redirect('budget/pendingIssue');
}
}
Model
function approveIssues($id)
{
$this->db->update('finance_budget_issue', array('transfer_status'=>'Approved'), array('id' => $id));
$this->db->update('finance_budget', array('transfer_status'=>'Approved'), array('budget_id' => $id));
if ($this->db->affected_rows()) {
$activity=FZ_Controller::activity('approve','finance_budget_issues',$id,NULL);
$this->db->insert('finance_user_activity',$activity);
return true;
}
return false;
}
When I press the Approved button in my view the system shows "Error". If I remove the line, $this->db->update('finance_budget', array('transfer_status'=>'Approved'), array('budget_id' => $id));
in my model the operation is executing successfully and shows the "Allocation Approved successfully ..!!" Message.
Desired Output
I also need the transfer_status of finance_budget table should be into "Approved".

You can try this Model Code
function approveIssues($id) {
$this->db->set('finance_budget.transfer_status','Approved');
$this->db->set('finance_budget_issue.transfer_status','Approved');
$this->db->where('finance_budget.budget_id', $id);
$this->db->where('finance_budget_issue.id', $id);
$this->db->update('finance_budget JOIN finance_budget_issue ON finance_budget.budget_id = finance_budget_issue.id');
if ($this->db->affected_rows()) {
$activity=FZ_Controller::activity('approve','finance_budget_issues',$id,NULL);
$this->db->insert('finance_user_activity',$activity);
return true;
}
return false;
}
i think it's very helpful for you.

Related

Yii2 findBySql: How to specify $params?

Yii2 provides ActiveRecord::findBySql für raw SQL queries:
public static yii\db\ActiveQuery findBySql ( $sql, $params = [] )
Since there is no hint in the documentation: How to specify $params?
UPDATE
The reason there isn't any docs about the params passed to the findBySql() method is because the method returns the instance of ActiveQuery and if you see the last line of this method in yii\db\ActiveRecord.php it sets the $params via $query->params($params), means the yii\db\ActiveQuery function params($params) which defines the $params as
$params list of query parameter values indexed by parameter
placeholders. For example, [':name' => 'Dan', ':age' => 31].
I guess you should try the following way if lets say you have a table with name product
+----+-----------------+------------+--------+
| id | name | is_deleted | price |
+----+-----------------+------------+--------+
| 1 | shugal | 1 | 65.00 |
| 2 | spoon | 1 | 55.00 |
| 4 | kettle | 1 | 15.00 |
| 5 | spoon | 0 | 15.00 |
| 6 | plates | 0 | 105.00 |
| 7 | dishes | 0 | 15.00 |
| 8 | forks | 0 | 15.00 |
| 10 | pressure cooker | 0 | 203.00 |
| 16 | shugal | 1 | 65.00 |
| 17 | something | 0 | 25.00 |
| 25 | multi product | 0 | 0.00 |
| 66 | pans | 0 | 15.00 |
+----+-----------------+------------+--------+
using the following code you can select all the products that are deleted using params
$q = Product::findBySql(
"SELECT * FROM product where is_deleted=:deleted",
[':deleted' => 1]
)->all();
Hope this helps

Get the DISTINCT id of users and find the MAX of their column then UPDATE, LARAVEL

What I want to do is, the distinct id based on the max value of the associated column and then update a column accordingly.
For example
id | name | total | description | updateThis
1 | john | 100 | example | 0
2 | dave | 300 | example | 0
2 | johno | 500 | example | 0
4 | derik | 900 | example | 0
5 | Sam | 1000 | example | 0
4 | bool | 12200 | example | 0
1 | john | 1200 | example | 0
5 | john | 300 | example | 0
I want it to look like this:
id | name | total | description | updateThis
1 | john | 1200 | example | 1
2 | johno | 500 | example | 1
4 | bool | 12200 | example | 1
5 | Sam | 1000 | example | 1
I am using Query Builder not the eloquent way of doing it, either would be a useful answer and if someone can give both that would be awesome too, I just need help thanks.
You can use this:
$rows = DB::table('table')
->select('id', DB::raw('max(total) as total'))
->groupBy('id')
->get();
foreach($rows as $row) {
DB::table('table')
->where('id', $row->id)
->where('total', $row->total)
->update(['updateThis' => 1]);
}

MySQL return prioritizes value else return other value

I have a table (This is a mock-table),
+------------+------+--------+
| Name | Code | Active |
+------------+------+--------+
| Sales | 55 | 1 |
| Sales | 55 | 0 |
| IT | 22 | 1 |
| Production | 33 | 1 |
| Production | 33 | 0 |
| Marketing | 77 | 0 |
| Marketing | 77 | 0 |
+------------+------+--------+
And I want to return a list of distinct names and codes. However, I want to determine if the department is active or not. so if Sales has a 1 in active and a 0 in active they are active, but is they had only zeros then they are not.
I've tried a variety of methods and read through a few dozen SO post, but am not gaining any progress.
The output I am trying to achieve is:
+------------+------+--------+
| Name | Code | Active |
+------------+------+--------+
| Sales | 55 | 1 |
| IT | 22 | 1 |
| Production | 33 | 1 |
| Marketing | 77 | 0 |
+------------+------+--------+
How can I prioritize the Active column to a value of 1, but still return an entry if all entries with the same code have a value of 0 (such as marketing)?
GROUP BY name and code and get the maximum value of Active. (Assuming 0 and 1 are the possible values for Active column)
SELECT Name,Code,MAX(Active) active
FROM tablename
GROUP BY Name,Code

Laravel - SUM and balane query

I have a Laravel application. I am trying calculate the SUM of column and balance. Can you please help me how to write the SQL for this.
+---------+----------+--------+----------+----------+------------+
| pay_id | username | income | outgoings| balance | date |
+---------+----------+--------+----------+----------+------------+
| 1 | john | 1000 | | 1000 | 00.00.2016 |
| 2 | jack | | 500 | 500 | 00.00.2016 |
| 3 | john | 1500 | | 2000 | 00.00.2016 |
| 4 | bill | | 1000 | 1000 | 00.00.2016 |
+---------+----------+--------+----------+----------+------------+
2500 1500
If you're using Eloquent:
Model::where('username', 'john')->sum('balance');
https://laravel.com/docs/5.3/eloquent#retrieving-single-models
If you want to sum multiple columns then you have to us DB::raw
$data = Model::get([
DB::raw('SUM(income) AS total_income'),
DB::raw('SUM(outgoings) AS total_outgoings'),
DB::raw('SUM(balance) AS total_balance')
]);
dd($data);
Or
$data = Model::select(
DB::raw('SUM(income) AS total_income'),
DB::raw('SUM(outgoings) AS total_outgoings'),
DB::raw('SUM(balance) AS total_balance')
)
->get();
dd($data);

MySQL query with WHERE and CASE

I do not really know if this is possible to do this but I will expose my problem.
I have two tables cases and progress
cases
+----------+--------------+---------------------+---------+------+
| id_cases | name | date_surgery | archive | done |
+----------+--------------+---------------------+---------+------+
| 1 | Cranioplasty | 2016-02-01 00:00:00 | 1 | 0 |
| 2 | Cranioplasty | 2016-02-02 00:00:00 | 0 | 0 |
| 3 | Other | 2016-02-03 00:00:00 | 0 | 0 |
| 4 | Osteotomy | 2016-02-04 00:00:00 | 0 | 0 |
| 5 | Bone Tumor | 2016-02-05 00:00:00 | 1 | 1 |
+----------+--------------+---------------------+---------+------+
progress (which contains thousands of records)
+-------------+---------+---------+---------+
| id_progress | task_id | case_id | current |
+-------------+---------+---------+---------+
| 1 | 103006 | 1 | 0 |
| 2 | 103002 | 1 | 1 |
| 3 | 103003 | 1 | 1 |
| 4 | 201006 | 5 | 0 |
| 5 | 201007 | 5 | 1 |
| .... | ... | ... | ...|
+-------------+---------+---------+---------+
The link between the tables is cases.id_cases = progress.case_id
I want to select all cases with archive and done = 0. I also want to get some progress that are linked to this case
I tought about a condition to select a specific range of task_id related to the result of cases.name.
So basically I want this
SELECT id_cases, name, date_surgery, task_id, current
FROM cases
LEFT JOIN progress on progress.case_id = cases.id_cases
WHERE archive = 0 AND done = 0
But if name is Cranioplasty I just want progress.task_id that are equal to 103006, 103002 and 105002. For Bone Tumor I want 201006, 205003 and 207001. And this for each different name.
There is no logic between the id_cases and the task_id. I must hardcode this.
I tried differents things but none suceeded
SELECT id_Cases, name, date_surgery, task_id, current
from cases
left join progress on progress.case_id = cases.id_cases
where archive = 0 and done = 0
and case when name='Cranioplasty' then task_id=103006 and task_id=103002 else
case when name='Bone Tumor' then task_id=201006 else
case when name='Osteotomy' then task_id=301002 else
case when name='MBIO' then task_id=401006 end end end end
order by name, date_surgery
In fine I try to get this result (task_id is not important, I just want to result of current)
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
| case | name | date_surg | task_1 | 1_res | task_2 | 2_res | task_3 | 3_res |
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
| 1 | Cranioplasty | date | 103006 | 0 | 103002 | 0 | 105002 | 1 |
| 1 | Cranioplasty | date | 103006 | 1 | 103002 | 1 | 105002 | 0 |
| 1 | Cranioplasty | date | 103006 | 1 | 103002 | 0 | 105002 | 1 |
| 2 | Cranioplasty | date | 103006 | 0 | 103002 | 1 | 105002 | 0 |
| 2 | Cranioplasty | date | 103006 | 1 | 103002 | 0 | 105002 | 1 |
| 2 | Cranioplasty | date | 103006 | 0 | 103002 | 1 | 105002 | 1 |
| 3 | Bone Tumor | date | 201006 | 1 | 205003 | 0 | 205005 | 0 |
| 3 | Bone Tumor | date | 201006 | 0 | 205003 | 1 | 205005 | 1 |
| ... | | | | | | | | |
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
PS : I just put my table as an example to help understanding the problem. It does not includes all the records
I know that I can use temporary or virtual table but I wanted to know how to resolve this with only a query
Well, anyway its bad practice to hardcode this relations between name and task id. You need to store them in database or smthng. So you can join that table and do it in 1 query.
If you cant or dont want to its better to save them atleast to an array so you can dynamically generate query part with this conditions if its possible.
select
a.id_cases,
a.name,
b.task_id,
b.current
from
cases a
left join
progress b ON b.case_id = a.id_cases
where
a.archive = 0
and a.done = 0
and (
(b.task_id in (103006,103002,105002) and a.name = 'Cranioplasty')
OR (b.task_id in (201006,205003,207001) and a.name = 'Bone Tumor')
)
If you can use any language to generate this part
and (
(b.task_id in (103006,103002,105002) and a.name = 'Cranioplasty')
OR (b.task_id in (201006,205003,207001) and a.name = 'Bone Tumor')
)
Do it. For example in php
foreach($arRealtions as $name => $taskIDs)
{
$query .= '(b.task_id in ('.implode(',',$taskIDs).') and a.name = "'.$name.'")';
}