extract string from string in mysql query - mysql

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;

Related

MySQL 8 update with Replace() or Regex

How can i update data using replace or regex-like method from
id | jdata
---------------
01 | {"name1":["number","2"]}
02 | {"val1":["number","12"],"val2":["number","22"]}
to
id | jdata
---------------
01 | {"name1":2 }
02 | {"val1": 12,"val2":22 }
I need to make a proper json entry for numbers and replace an array with a number from that array. Column "jdata" can have any number of similar attributes from the example. Something similar to this would do:
UPDATE table SET jdata = REPLACE(jdata, '["number","%d"]', %d);
Two ways:
The long, more clumsy way, using JSON_ARRAY:
UPDATE table1,
(
SELECT
id,
JSON_EXTRACT(jdata, "$.name1[0]") as A,
JSON_EXTRACT(jdata, "$.name1[1]") as B,
JSON_EXTRACT(jdata, "$.val1[0]") as C,
JSON_EXTRACT(jdata, "$.val1[1]") as D,
JSON_EXTRACT(jdata, "$.val2[0]") as E,
JSON_EXTRACT(jdata, "$.val2[1]") as F
FROM table1
) x
SET jdata = CASE WHEN table1.id=1 THEN JSON_ARRAY("name1",x.B)
ELSE JSON_ARRAY("val1",x.D,"val2",F) END
WHERE x.id=table1.id;
Or using JSON_REPLACE:
update table1
set jdata = JSON_REPLACE(jdata, "$.name1",JSON_EXTRACT(jdata,"$.name1[1]"))
where id=1;
update table1
set jdata = JSON_REPLACE(jdata, "$.val1",JSON_EXTRACT(jdata,"$.val1[1]"),
"$.val2",JSON_EXTRACT(jdata,"$.val2[1]"))
where id=2;
see: DBFIDDLE for both options
EDIT: To get more depth in the query, you can start with below, and create a new JSON message from this stuff without the number:
WITH RECURSIVE cte1 as (
select 0 as x
union all
select x+1 from cte1 where x<10
)
select
id,
x,
JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))) j,
JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))))) v,
JSON_UNQUOTE(JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[0]"))) v1,
JSON_UNQUOTE(JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[1]"))) v2
from table1
cross join cte1
where x<JSON_DEPTH(jdata)
and not JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]")) is null
order by id,x;
output:
id
x
j
v
v1
v2
1
0
name1
["number", "2"]
number
2
2
0
val1
["number", "12"]
number
12
2
1
val2
["number", "22"]
number
22
This should take care of JSON message which also contains values like val3, val4, etc, until a maximum depth which is now fixed to 10 in cte1.
EDIT2: When it is just needed to remove the "number" from the JSON message, you can also repeat this UPDATE until all "number" tags are removed (you can repeat this in a stored procedure, I am not going to write the stored procedure for you 😉)
update
table1,
( WITH RECURSIVE cte1 as (
select 0 as x
union all
select x+1 from cte1 where x<10
) select * from cte1 )x
set jdata = JSON_REMOVE(table1.jdata, CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[0]"))
where JSON_UNQUOTE(JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[0]"))) = "number"
An example, where I do run the update 2 times, is in this DBFIDDLE

Adding value from select query using DBquery in Yii2

i want to add value(string) in my select query..iam using dbquery..do anyone know how to do this?
$tableA = (new \yii\db\Query())
->select("sm_wp.no_agenda,mfwp.nama_wp,sm_wp.jenis_surat,
sm_wp.nomor_surat, sm_wp.tgl_surat,sm_wp.perihal")
->from('sm_wp')
->leftjoin('mfwp', 'sm_wp.id_mfwp = mfwp.id')
;
from that query i got this table in my gridview
no_agenda nama_wp jenis_surat nomor_surat tgl_surat perihal
--------- ------ ----------- ----------- --------- -------
1 xx 1 22 21/10/2019 bla
i want that table become like this
no_agenda kategori nama_wp jenis_surat nomor_surat tgl_surat perihal
--------- ------ ----------- ----------- --------- ------- -------
1 foo xx 1 22 21/10/2019 bla
2 foo yy 1 22 21/10/2019 ble
i want to add kategori in my gridview with same value (foo)..thx
You need to escape the quoting by using \yii\db\Expression
$tableA = (new \yii\db\Query())
->select(
[
new Expression(
'sm_wp.no_agenda,mfwp.nama_wp,sm_wp.jenis_surat,
sm_wp.nomor_surat, sm_wp.tgl_surat,sm_wp.perihal,
"foo" as kategori'
),
]
)
->from('sm_wp')
->leftjoin('mfwp', 'sm_wp.id_mfwp = mfwp.id')

MySQL - How do I update the decimal column to allow more digits after dot

I have this decimal(20,2) column in MySQL tables:
no
-----
10.01
10.09
10.10
10.11
10.19
10.99
What is the easiest way to update that decimal value to
no
-------
10.001
10.009
10.010
10.011
10.099
..
10.100
10.101
If I only change column to decimal(20,3), I have 10.010, 10.020 ... 10.990
That should work:
UPDATE TableName
SET no = no DIV 1 + MOD(no, 1) / 10
The two following functions do the following:
no DIV 1 => 10.019 DIV 1 = 10
MOD(no, 1) => MOD(10.019, 1) = 0.019

Change FROM part of a query depending on column value

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.

Merge tables into One WITH same generated number in both new tables

I found some options to run a mysql query to migrate/split one table into 2 new tables, but one of the fields I would like to create on the new table has to be the same as in the other new table:
So from the "From_payments" table, I would like to create 2 new tables called: "To_paymenttransaction" and "To_paymentinfo". A lof of the field are predefined and some are from the old table. The only problem is that the predefined field "paymentinfoid" has to be the same is both new tables.
**To_paymenttransaction** --- < --- **From_payments**
paymenttransactionid ------- < --- (Generate next available number in this column)
paymentinfoid -------------- < --- (Generate next available number in this column)
transactionid --------------- < --- txn_id
state ---------------------- < --- (Set all to "1")
amount -------------------- < --- mc_gross
currency ------------------- < --- mc_currency
dateline -------------------- < --- payment_date
paymentapiid --------------- < --- (Set all to "1")
request -------------------- < --- (Set all to "NULL")
reversed ------------------- < --- (Set all to "0")
**To_paymentinfo** -----------<
paymentinfoid -------------- < --- (Same generated number that goes to the paymentinfoif field in To_paymenttransaction table )
hash ----------------------- < --- (Set all to "Imported")
subscriptionid --------------- < --- (Set all to "1")
subscriptionsubid ------------ < --- ("2" IF above field mc_gross is 4, "1" IF above field mc_gross is 6, "0" IF above field mc_gross is 10)
userid ---------------------- < --- userid
completed ------------------ < --- (Set all to "0")
Any ideas?
All help is greatly appreciated.
Maybe generate the paymentinfoid on the original table before you split it. Then you can copy that single entry into each of the new tables.