Exact strings in a column in SQL - mysql

I am trying to use mysql to solve the question below.
Any idea how should I make it work? Thank you.
Tried to use the code below but extracted duplicate strings in two columns and it's hard-code so it's not working..
SELECT itemid, SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 1), ',', -1) 'type one',
SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 2), ',', -1) 'type two',
SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 3), ',', -1) 'type three',
SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 4), ',', -1) 'type four'
FROM data
Question:
To extract items with more than 3 types
|itemid|shopid|item_name|item_type|price|stock|creation_date|
|1|10000|clothes|{}|5|100|27/1/2018|
|2|10000|dress|{Pink: 20, Black: 20, Grey: 20}|20|100|20/2/2018|
|3|10001|t-shirt|{S: 2, M: 2, L: 2, XL: 2}|2|50|1/1/2018|
|4|10002|socks|{us5.5: 1, us9: 1, us4.5: 1, us10: 1, us7: 1, us6: 1, us5: 1}|1|1000|4/1/2018|
|5|10002|Gloves|{S: 2, M: 2}|2|500|6/1/2018|
Expected result
|itemid |item_name |item_type|
|3 |t-shirt |{S: 2, M: 2, L: 2, XL: 2}|
|4 |socks |{us5.5: 1, us9: 1, us4.5: 1, us10: 1, us7: 1, us6: 1, us5: 1}|

This ought to do:
select itemid, item_name, item_type
from t
where length(item_type) - length(replace(item_type, ',', '')) >= 3;
You need a special case to tell 0 and 1 apart. It would not work if item_type contains ',' in either key or value of the json-like field (missing quoted around strings to be json).

You just need to count number of comma(,)>=3. Try below code:
SELECT
Itemid,Item_Name,Item_type
FROM myjson
where ROUND (
(
LENGTH(item_type)
- LENGTH( REPLACE ( item_type, ",", "") )
) / LENGTH(",")
)>=3

Related

Mysql month number to month name conversion

I have month value like "22018" in my column I need it like Feb-2018 in mysql workbench
You need to first extract the month from the date (considering it will have one or two digits), e.g.:
SELECT LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0');
This will give you 02. Now, you can extract the year with similar logic, e.g.:
SELECT SUBSTRING('22018', LENGTH('22018') - 4 + 1, LENGTH('22018'));
Finally, you can concatenate all these to get a string like 2018-02-01:
SELECT CONCAT(SUBSTRING('22018', LENGTH('22018') - 4 + 1, LENGTH('22018')),
'-',
LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0'), '-01');
Once this is done, you can use DATE_FORMAT function to get the required output:
SELECT DATE_FORMAT(CONCAT(SUBSTRING('22018', LENGTH('22018') - 4 + 1,
LENGTH('22018')),
'-',
LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0'), '-01'), '%M-%Y');

oracle11g regexp_replace for json

I have select:
select regexp_replace(regexp_substr('[{"date": "01_2016", "val":"100_22"},{"date": "02_2016","val": "200.10"}]'
,'"val":\s*("(\w| )*")', 1, level)
,'"val":\s*"((\w| )*)"', '\1', 1, 1) val
from dual
connect by regexp_substr('[{"date": "01_2016", "val":"100_22"},{"date": "02_2016","val": "200.10"}]', '"val":\s*("(\w| )*")', 1, level) is not null
;
If my value have format 100_10 it is ok. But I want 100.10 and this select not support this. How to write regexp_replace?
Use (\d+)_(\d+) to match only the numeric values separated by an underscore:
SELECT REGEXP_REPLACE(
'[{"date": "01_2016", "val":"100_22"},{"date": "02_2016","val": "200.10"}]',
'"val":"(\d+)_(\d+)"',
'"val":"\1.\2"'
)
FROM DUAL;
Thanks everybody. I found the solution
select regexp_replace(regexp_substr('[{"date": "01-2016", "val":"100.22"},{"date": "02-2016","val": "200.10"},{"date": "03-2016","val": "200.15"}]','"val":\s*("(\w|[..])*")', 1, level),'"val":\s*"((\w|[..])*)"', '\1', 1, 1) val, regexp_replace(regexp_substr('[{"date": "01-2016", "val":"100.22"},{"date": "02-2016","val": "200.10"},{"date": "03-2016","val": "200.15"}]' ,'"date":\s*("(\w|[-])*")', 1, level) ,'"date":\s*"((\w|[-])*)"', '\1', 1, 1) date_period from dual connect by regexp_substr('[{"date": "01-2016", "val":"100.22"},{"date": "02-2016","val": "200.10"},{"date": "03-2016","val": "200.15"}]', '"val":\s*("(\w|[..])*")', 1, level) is not null

How to format uuid string from binary column in MySQL/MariaDB

In MySQL/MariaDB the most efficient way to store uuid is in a BINARY(16) column. However, sometimes you want to obtain it as a formatted uuid string.
Given the following table structure, how would I obtain all uuids in a default formatted way?
CREATE TABLE foo (uuid BINARY(16));
The following would create the result I was after:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
FROM foo;
MySQL 8 adds two new UUID functions:
UUID_TO_BIN
BIN_TO_UUID - this is the one you're looking for
So:
SELECT BIN_TO_UUID(uuid) FROM foo
In earlier (prior to 8) versions you can create a function in MySQL like the following:
CREATE
FUNCTION uuid_of(uuid BINARY(16))
RETURNS VARCHAR(36)
RETURN LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
));
And then simply use it in your queries:
SELECT
uuid_of(id)
name,
age
FROM users
And it produces:
(c6f5703b-fec2-43fd-8f45-45f06583d450, Some name, 20)
If you are looking for the opposite, i.e., how to convert from string to binary, perhaps to do a join or something, this is covered here : Convert UUID to/from binary in Node
This piece of SQL run on Mysql 5.7 helped lock in the concept for me:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 1, 8), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 9, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 13, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 17, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 21)
))
The output is 43d597d7-2323-325a-90fc-21fa5947b9f3.
string -> binary
So UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', '')) to convert a UUID to binary during an INSERT / UPDATE / JOIN / SELECT whatever, and
binary -> string
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
The correct result is generated by the script below, the other scrips generated a UUID however not the right one.
CONCAT(
substr(hex(Id), 7, 2), substr(hex(Id), 5, 2), substr(hex(Id), 3, 2), substr(hex(Id), 1, 2), '-'
, substr(hex(Id), 11, 2) , substr(hex(Id), 9, 2) , '-'
, substr(hex(Id), 15, 2) , substr(hex(Id), 13, 2) , '-'
, substr(hex(Id), 17, 4) , '-'
, substr(hex(Id), 21, 12)
)
Results running the other scripts generated wrong UUID as per below:
Expected UUID - 2e9660c2-1e51-4b9e-9a86-6db1a2770422
What was generated - c260962e-511e-9e4b-9a86-6db1a2770422
As you can see they are different.
Here's an alternative using concat_ws
Store raw uuid in a variable #x
SELECT #x := hex(uuid)
FROM foo;
Use CONCAT_WS and SUBSTR to parse human readable UUID
SELECT
LOWER(CONCAT_WS('-',
SUBSTR(#x, 1, 8),
SUBSTR(#x, 9, 4),
SUBSTR(#x, 13, 4),
SUBSTR(#x, 17, 4),
SUBSTR(#x, 21)
)) AS uuid;
According to this Jira ticket https://jira.mariadb.org/browse/MDEV-15854 UUID_TO_BIN and BIN_TO_UUID did not make into the Mariadb Server release 10.5. If you are using this version and under of Mariadb Server you will have to use a custom implementation mentioned above.

replace() concat() and substr() add character at specific location in string cannot get the position right

End result: all 3 fields should be merged (solved OK), and the character "T" should be added as the 5th character in the merged string (no other characters should be removed or altered in sequence). (see all specifics below).
What am I doing wrong?
Data is in the following format:
data1: AL
data2: 33 0230S 0440E
data3: SW
Here is my current sql:
replace(concat(b.data1,
substr(b.data2, 4, 1),
'T',
substr(b.data2, 1),
b.data3), ' ', '')
AS MergedData
The final output should look like:
AL33T0230S0440ESW
I've been able to get the "T" placed at random locations, but cannot get it consistently added as the 5th character from the start of the string.
Use:
replace only on data2 (because that's the only field that needs it), then
concat() to join it all up, and finally
the insert() function to insert the T
(Don't use substr at all)
insert(concat(data1, replace(data2, ' ', ''), data3), 5, 0, 'T')
Here's a test:
set #data1 := 'AL', #data2 := '33 0230S 0440E', #data3 := 'SW';
select
insert(concat(#data1, replace(#data2, ' ', ''), #data3), 5, 0, 'T')
as MergedData;
Output:
+-------------------+
| MergedData |
+-------------------+
| AL33T0230S0440ESW |
+-------------------+
Random locations seems odd, this seems to work though;
replace(concat(b.data1,
substr(b.data2, 1, 2),
'T',
substr(b.data2, 4),
b.data3), ' ', '')
Demo here.
Find the position of the first space in data2, replace it with T, remove the rest of the spaces in the resulting string, then concatenate it with the two other values:
CONCAT(
b.data1,
REPLACE(INSERT(b.data2, LOCATE(' ', b.data2), 1, 'T'), ' ', ''),
b.data3
) AS MergedData

Mask values on mysql database

I have a column with values like this:
01709100011
I need to transform it to:
017.091.0001-1
The values have always the same characters number.
Both columns are varchar
Thanks in advance for any help.
SELECT CONCAT(SUBSTRING(test, 1,3),'.',SUBSTRING(test,4,3),'.',SUBSTRING(test,7,4),'-',SUBSTRING(test,11,1)) FROM test;
In the above example I used the table test and values in column test.
SELECT CONCAT_WS( "-", CONCAT_WS( ".", SUBSTRING( foo, 0, 3 ), SUBSTRING( foo, 3, 3 ), SUBSTRING( 6, 4 )), SUBSTRING( foo, 10 , 1 )) FROM bar WHERE 1=1;