We have an inventory feature where we generate Bills. There is an Edit Bill API call. We have implemented it as PATCH call.
A Bill with id = 1 has 2 LineItems :
| Stock Id | Qty | Rate |
| 10 | 2 | 10 |
| 11 | 3 | 20 |
Now lets say I want to change the quantity for stock Id : 10 to 5 and I want to change the rate for stock Id : 11 to 40
We have represented it as PATCH Call :
bill : {
id : 1
lineItems : [
{
stockId : 10,
qty : 5,
},
{
stockId : 11,
rate : 40
}
]
}
In the backend we run following query :
UPDATE `billlineitem`
SET `rate` = ( CASE
WHEN stockid = 11 THEN '40'
ELSE rate
END ),
`qty` = ( CASE
WHEN stockid = 10 THEN 5
ELSE qty
END ),
`updated_billitemquantity_at` = '2019-09-06 05:16:06.219'
WHERE `bill_id` = '1'
AND `stockid` IN ( 10, 11 )
Is it ok, in the above case when there is no change for an attribute then the else clause will take the value from the database for that attribute. The above update statement is run in a transaction.
Is this a correct approach? Will this do an update for every attribute for every stock Id. Is there a better approach?
We are using MySQL DB.
What you've written should work, but it will get very complex if you have to update different columns for many different stock IDs. It would probably be simpler, and maybe better performance, to do a separate query for each ID.
BEGIN TRANSACTION;
UPDATE billlineitem
SET rate = '40', `updated_billitemquantity_at` = '2019-09-06 05:16:06.219'
WHERE stockid = 10;
UPDATE billlineitem
SET qty = 5, `updated_billitemquantity_at` = '2019-09-06 05:16:06.219'
WHERE stockid = 11;
COMMIT;
I have a large MySQL table with sorted data. When I need to find a starting point, I perform a binary search to find the lower bound ID (auto increment). The only problem is once some data is deleted, I need to look at the first existing row with a lower ID if the ID given by the algorithm doesn't exist. How should I modify this code to achieve that?
$l = 1;
$h = $max; //SELECT MAX(id)
while ($h - $l > 1){
$m = ($h + $l) / 2;
$q = mysqli_query($db, "SELECT col FROM tab WHERE id=". floor($m));
$result = array();
while($result[] = mysqli_fetch_row($q)){;}
if ($result[0][0] < $val) $l = $m;
else $h = $m;
}
echo round($m);
For example I want to find which rows have the value of col greater than 12345 and the table has max ID 10000. I start by looking at row 5000, where the col = 9000, then 7500 (col = 13000), then 6250 has been deleted, so I start looking for the 1st existing row with ID < 6250 and I find that 6245 has col = 10500. Now I'm looking between IDs 6873 and 7500 etc.
The right way to do this
So you have a table like this:
| ID | col |
---------------
| 1 | 15 |
| 3 | 155 |
| 18 | 9231|
| 190 |14343|
| 500 |16888|
You can get find 14343 with the following query:
SELECT ID, col FROM the_table WHERE col>12345 LIMIT 1;
To make it faster, you'd need to add an index (index word is worth googling)
ALTER TABLE `the_table` ADD INDEX `col` (`col`);
After that mysql will create a tree structure internally and will be doing binary searches on it for you.
This will be working much faster as you'll avoid multiple network roundtrips + other per request expenses (query parsing, optimization, all the locks & mutexes, ...)
Answer to your question
I need to look at the first existing row with a lower ID
E.g. you'd like to get first row with an ID < than 300, you do this (limit is what makes the query return only 1 result):
SELECT col FROM the_table WHERE ID < 300 LIMIT 1;
I have a table named tasks with a columns named task_type, task_group and keyid. Then there is another table named task_groups with two columns: keyid and name.
If a task has a task_type equal to 2 then I know that task_group contains the keyid value for the entry in table task_groups that contains the name of the task. If task_type is any other value then task_group is -1. So what i want is to write a query that returns the task type always AND the name of the task_group but only if task_type is 2, all of this for a given task.
For this I use a script with the following logic (3 is a tasks.keyid example):
SELECT task_type,task_group AS tgid FROM tasks WHERE keyid = 3;
if (task_type == 2)
SELECT name FROM task_group WHERE keyid = tgid
Is there a way to write one query to do this?
EDIT: Adding some sample data
Table task:
+++ keyid +++ task_group +++ task_type
+++ 25 +++ -2 +++ 0
+++ 26 +++ -2 +++ 1
+++ 27 +++ 132 +++ 2
+++++++++++++++++++++++++++++++++++++++
Table task_groups:
+++ keyid +++ name
+++ 132 +++ a task group
+++++++++++++++++++++++++++++++++++++++
Expected output when replacing the value 3 in the above code would be
(tasks.keyid = 25) task_type = 0, task_group_name = ""
(tasks.keyid = 26) task_type = 1, task_group_name = ""
(tasks.keyid = 27) task_type = 2, task_group_name = "a task group"
I hope this is good enough.
Try this:
SELECT
t.task_type, t.task_group AS tgid,
IF (t.task_type = 2, g.name, '') AS group_name
FROM tasks t
LEFT JOIN task_group g ON t.task_group = g.keyid
WHERE t.keyid = 3
;
this query should return group name if type = 2 or empty string otherwise.
I have this query:-
select col_str,
getVal,another_str,resultVal_str from tablename
Getting results like this:
col_str getVal another_str
'11,12,33,54,1,44' '12' '9,5,4,8,7'
'11,12,33,54,1,44,10,12,11,12,12' '44' '9,5,4,8,7,6,3,5,2,4,2'
'11,12,33,54,1,44' '999' '9,5,4,8,7,4'
'11,12,33' '0' '9,5,4'
----- ---- -----
----- ---- -----
----- ---- -----
The columns col_str,getVal,another_str came from table and the column resultVal_str want to calculate based on remaining three column,
Logic for resultVal_str -
See first record getVal having value 12 and col_str having 12 at location number 2 then see the location number two in another_str is 5, so the resultVal_str is 5 and so on. See below:
col_str getVal another_str resultVal_str
'11,12,33,54,1,44' '12' '9,5,4,8,7' 5
'11,12,33,54,1,44,10,12,11,12,12' '44' '9,5,4,8,7,6,3,5,2,4,2' 6
'11,12,33,54,1,44' '999' '9,5,4,8,7,4' 0
'11,12,33' '0' '9,5,4' 0
----- ---- ----- ---
----- ---- ----- ---
----- ---- ----- ---
How can i add the next column resultVal_str with getting result like above ?
first you need to fin the position of getVal in col_str using FIND_IN_SET function.
once you get the position you can find the resultVal from same location in another_str using SUBSTRING_INDEX function as:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(another_str,
",", (FIND_IN_SET(getVal, col_str))),
",", - 1) AS resultVal_str
FROM tablename;
test:
SET #getVal = '12', #col_str = '11,12,33,54,1,44', #another_str = '9,5,4,8,7';
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(#another_str, ",", (FIND_IN_SET(#getVal, #col_str))), ",", - 1) AS resultVal_str;
I am using JTable. Suppose I have a table which contains the following information -
**col1 col2 col3 col4**
row1 --- value1 --- ---
row2 --- value2 --- ---
row3 --- value3 --- ---
row4 --- value3 --- ---
row5 --- value1 --- ---
row6 --- value1 --- ---
row7 --- value2 --- ---
row8 --- value1 --- ---
I need to copy the rows which have the value of col2 as "value1" into another table.
For selecting the rows by hand (mouse click) there is a function called - getSelectedRows() where the work will be over in seconds i.e.
int [] rows = inputTable.getSelectedRows(); // "rows" is getting the array of indexes of the rows in the table
but now I need to do the same thing without mouse selection. i.e. int [] rows should get the rows indexes without using the above method but I can use any other methods without mouse selection that is...
List<String> searchedRows = new ArrayList<String>();
for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
String value = (String)table.getValueAt(rowIndex,varColNumber);
if ("value1".equals(value)) {
searchedRows.add(rowIndex);
}
}
// here in the List searchedRows you have the rows numbers where the column is equals to the string "value1".
Hope it helps..