I am trying to update my table using update batch.
so I have this table columns
ID | Description | Total
1 Test 1 10
2 Test 2 15
3 Test 3 20
My main goal is to update the Total column using update batch, so i will not need to update them one by one.
so I don't have to do this one by one on my loop, instead i can just do update_batch
UPDATE table
SET Total = Total + 10
WHERE ID = 1;
UPDATE table
SET Total = Total + 25
WHERE ID = 2;
UPDATE table
SET Total = Total + 30
WHERE ID = 3;
How can I do this using update_batch?
Here is the code the I currently have
Controller:
foreach($total_debit as $list){
$data[] = array(
"ID" => $list->ID,
"Total" => Total + $list->value_to_be_added, //10
);
}
$this->Employee_model->update_total_value($data);
Model:
public function update_total_value($data){
$this->db->update_batch('employees', $data,"ID");
}
Can anyone help me if this is possible to do?
I have this structure in table named customer_type_total_avg
USEDID CID TYPE PERCENTAGECOMPLETED
------- ---- ---- ------------------
1 6 external 12
1 6 external 50
1 6 internal 50
1 6 external 84
1 6 internal 100
1 6 external 100
function getCustomerprogress($where) {
$progress = 0;
$cid = $where["cid"];
$userid = $where["userid"];
$sql = "SELECT
TRUNCATE(avg(t.percentage),1) as avg_percentage
FROM
(SELECT
percentagecompleted as 'percentage'
FROM
customer_type_total_avg
WHERE
userid = $userid and cid = $cid) AS t";
$query = $this->db->query($sql);
if ($query->num_rows() > 0) {
foreach ($query->result_array() as $row) {
$progress = $row["avg_percentage"];
}
}
return $progress;
}
I need a SELECT query to find the total average of the rows WHERE USERID and CID are matching
NOTE : we should include this below condition also in SELECT query to get average
When the "TYPE" is 'external' it should consider whatever the value in column "percentagecompleted"
When the "TYPE" is 'internal' and percentagecompleted = '50',Then it should replace the value of percentagecompleted = '0' and it should consider the row for finding the average
Example: From the above table, we have matching six rows and it will consider the external type percentagecompleted value for average calculation and in third row the percentagecompleted is '50' for internal, what i need is to replace the value to '0' and find the average for total number of rows
USEDID CID TYPE PERCENTAGECOMPLETED
------- ---- ---- ------------------
1 6 external 12
1 6 external 50
1 6 internal 0
1 6 external 84
1 6 internal 100
1 6 external 100
You can use CASE.
SELECT AVG(CASE WHEN TYPE='internal' and PERCENTAGECOMPLETED=50
THEN 0
ELSE PERCENTAGECOMPLETED END) AS AVG
FROM CUSTOMER_TYPE_TOTAL_AVG
CHECK DEMO HERE
Not sure if my title accurately explains what I'm trying to do, but here is my use case:
I have a database of Id's 1 = n, let's call it 500 total records.
I want to first get the week number in PHP $week = date('W') so this week is 48.
Then I want to return 3 unique Id's that would always return the same Id's for that week. So for example.
Week 1 = Id's 1,2,3
Week 2 = Id's 4,5,6
Week 3 = Id's 7,8,9
Week 4 = Id's 10,11,12
Week 5 = Id's 13,14,15
Week 6 = Id's 16,17,18
And so on.
My approach was to start with week 1, specifying the 3 Id's, then multiply the week by 2 for the 2nd week, then each subsequent week continue to multiply by 2 and add $i = 1 each week and incrementing $i++ each week and selecting the next 3 Id's from the starting number. My solution below seems to work, but it feels kinda hokey.
$weeks = array(1,2,3,4,5,6,7);
$output_arr = array();
$ids_arr = array();
$id1 = 1;
$id2 = $id1 + 1;
$id3 = $id1 + 2;
$i = -1;
foreach ($weeks as $week) {
if ($week == 1) {
$ids = array($id1, $id2, $id3);
$ids = implode(', ', $ids);
} else {
$id1 = $week * 2 + $i;
$id2 = $id1 + 1;
$id3 = $id1 + 2;
$ids = array($id1, $id2, $id3);
$ids = implode(', ', $ids);
}
$output_arr[$week] = $ids;
$i++;
}
So my end result is:
$output_arr = Array ( [1] => 1, 2, 3 [2] => 4, 5, 6 [3] => 7, 8, 9 [4] => 10, 11, 12 [5] => 13, 14, 15 [6] => 16, 17, 18 [7] => 19, 20, 21 )
Which is what I want, but is there a simpler cleaner way? And, BONUS HELP NEEDED it would be a lot better if it could handle a table with non-sequential Id's. In my case, my ID's need to be sequential, if I have a break in Id's EX: 1,2,3,4,6,7,8,10 it would mess up the output array.
Thanks for the help.
No need to store all weeks in array, a simple function can do the job:
$ids = array(1,2,3,4,6,7,8,10);
function weekIds($pWeek){
$wids = array();
for($i=1;$i<=3;$i++)
$wids[] = ($pWeek-1)*3+$i;
return $wids;
}
$seq = weekIds(2);
foreach($seq as $s)
$nonSeq[] = $ids[$s-1];
echo 'Sequential: ' .print_r($seq,true).PHP_EOL;
echo 'Non-Sequential: ' .print_r($nonSeq,true);
Output:
Sequential: Array
(
[0] => 4
[1] => 5
[2] => 6
)
Non-Sequential: Array
(
[0] => 4
[1] => 6
[2] => 7
)
If you are pulling all of the data out of your table, ORDER BY id and just call array_chunk($array, 3) on your resultset array and access the desired set-of-3 by subtracting 1 from the week number.
If you only need to pull the desired three rows from the table, then you can ORDER BY id and set the LIMIT "offset" to (week minus 1) times 3 then the "limit" to 3.
Alternatively, if you are not scared off by a bit of SQL magic, you can write a user-defined variable in your query so that all of the info is grouped readily available in your resultset.
SQL (SQL Demo)
SELECT
CEIL(r / 3) AS WeekId, GROUP_CONCAT(id) AS Ids
FROM (
SELECT
#rowid := #rowid + 1 AS r, id
FROM tableA
CROSS JOIN (
SELECT #rowid := 0
) cjoin
) sub
GROUP BY WeekId
Output:
| WeekId | Ids |
| ------ | ----- |
| 1 | 1,2,3 |
| 2 | 4,6,7 |
| 3 | 8,10 |
Now, if you don't actually intend to use every row of your database table, then best practice indicates that you should only retrieve the data that you intend to use.
To access a single set of 3 ids, use php to determine the current week number, divide it by three, round that number up to the next integer, then subtract one so that the LIMIT clause in the query uses 0 (for week 1) to target ids 1, 2, and 3; and 1 (for week 2) to target ids 4, 6, 7; etc.
Code: (SQL Demo)
$limit_offset = ceil(date('W') / 3) - 1;
$query = "SELECT id FROM your_table ORDER BY id LIMIT $limit_offset, 3";
p.s. The reason that I am not using pure SQL to perform this task is because: Can I use MySQL functions in the LIMIT offset .
I am building a user like system using PHP and MySQL.
THIS IS MY TABLE
--------------
ID value
---------------
1 1
2 0
3 1
4 1
5 1
6 0
I'm trying to write a mysql query in php, that only displays total value count, if the total value count is greater than 5. i.e only return the query as true if there are more than 5 records found in the table.
Can someone please help me? I've tried many things.
This is my code i have tried so far
$query = " SELECT COUNT(value) AS value,
CASE
WHEN value > 0 THEN value ELSE 0 END
FROM users
";
$query = $this->db->query($query);
$query->result_array();
if ($query->num_rows() > 0){
echo "more than 5 records are found";
}
THANKS
(EDIT - To make the question clearer)
So if we look at the table below (TABLE 1), value = 1 is found 6 times in the table. So the query should return true. This is because I am trying to count all values, where value = 1, and not value = 0. And I only want to return the query, if value = 1 is found 5 times or more.
TABLE 1
--------------
ID value
--------------
1 1
2 0
3 1
4 1
5 1
6 0
7 1
8 1
If we look at TABLE 2 below, value = 1 is only found 2 times in that table. So we return the query as false, because we need value = 1 to be found in the table more than 5 times to return true.
TABLE 2
--------------
ID value
--------------
1 1
2 0
3 1
4 0
5 0
6 0
7 0
8 0
I'd like to make this happen in the query and not using if statements outside the query using php. ie, if($results > 5) { return true}
THANKS
Hope this will help you :
You can use count_all to get the count and then get user records
$count = $this->db->count_all('users');
if ($count > 5)
{
$query = $this->db->get('users');
$records = $query->result_array();
print_r($records);
}
You could use following query to get data if there are 5 or more than 5 records exists
select *
from users u
where (
select count(*)
from users
) >= 5
Demo
Here is another demo if table has less than 5 rows
if you want to get the sum of values in the column value you can use this.
$data = $this->db->get('users')->result_array();
foreach ($data as $row) {
$num_value[] = $row['value'];
}
$num_value = array_sum($num_value);
if($num_value > 5){
echo 'value is more than 5';
}
else{
echo 'value is equal or less than 5';
}
I have a somewhat complex problem that needs fixing, for now I have the following table structure (task_schedule):
id taskid productid product_position
1 1 1 1
2 2 1 2
3 3 2 1
4 4 1 3
5 5 2 2
6 6 3 1
product_position works the following way: it should look at the productid and increment from the previous max value entry.
I accomplish this with the following query (probably easier to understand too):
INSERT into task_schedule (taskid, productid, product_position)
SELECT 1,1, max(product_position) + 1
FROM task_schedule
WHERE productid=1
(the values are of course attributed in the php backend)
I need a new column now though. Lets call it user_position, I'm going to recreate my table with an example:
id taskid productid product_position user_position
1 1 1 1 1
2 2 1 2 4
3 3 2 1 2
4 4 1 3 6
5 5 2 2 5
6 6 3 1 3
OK, so how this should work is: user_position should individually run through each entry and look at the productid, it should build a position list based on an even order of priority.
So if I ordered this by user_position I would get the following entry id list: 1 3 6 2 5 4
An example of what I need done in php:
Imagine the following list: red red red green green green green blue blue yellow
$array1 = array(array("red"), array("red"), array("red"));
$array2 = array(array("green"), array("green"), array("green"), array("green"));
$array3 = array(array("blue"), array("blue"));
$array4 = array(array("yellow"));
$Arrays= array ($array1, $array2, $array3, $array4);
foreach ($Arrays as $type => $list) {
$ArrayLength[]=count($list);
}
$MergeArray=array();
$flag=true;
for($i=0;$flag==true;$i++)
{
$flag=false;
for($j=0;$j < count($ArrayLength);$j++)
{
if( $i < $ArrayLength[$j] )
{
array_push( $MergeArray , $Arrays[$j][$i] );
$flag=true;
}
}
}
echo "<pre>".Print_r(json_encode($MergeArray), true)."</pre>";
This returns me a consistent list with the pattern I desire:
[["red"],["green"],["blue"],["yellow"],["red"],["green"],["blue"],["red"],["green"],["green"]]
All of the above is just an example of what I need, but implemented via MySQL.
I don't even know how to approach this issue now though, I need a way to insert new entries AND update the user_position column accordingly.
If I was to add a new entry into my table, with a new peoduct_id, this should be the end result:
id taskid productid product_position user_position
1 1 1 1 1
2 2 1 2 5
3 3 2 1 2
4 4 1 3 7
5 5 2 2 6
6 6 3 1 3
7 7 4 1 4
Notice how the user_position shifted to accommodate the new row.
I think this is a fairly complex problem to solve (or maybe my mysql is just THAT weak), I don't think there is a easy solution for this one, so any input you might have on how to approach this via mysql (mysql doing the heavy lifting would be fantastic), but I welcome a PHP solution as well with multiple queries and whatnot. Unfortunately I can't drop this column, it's easy to grab entries and let PHP sort my information, but I really need this implemented in the database.
Any input from the community would be great really.
Insert using the normal insert query which you are using
INSERT into task_schedule (taskid, productid, product_position, user_position)
SELECT 1,1, max(product_position) + 1, 0 FROM task_schedule WHERE productid=1;
And then update all the entries based on product_position using the below
SET #counter = 0;
UPDATE task_schedule SET user_position = #counter := #counter + 1 ORDER BY product_position asc, productid asc;
Here is the SQL fiddle link