how to randomize column data and mask data using mysql - mysql

DISCLAIMER: NONE OF THESE VALUES ARE TRUE/REAL, ITS JUST A PRACTICE ASSIGNMENT
how to randomize the last 6 digits of the DBS account and obscuring the first 4 digits of the NRIC number with x using mysql. All values were keyed in manually and do not relate to each other.
Current
Desired Result

Just use substring operations:
SELECT
CONCAT('XXXX', SUBSTRING(NRIC, 5, 4)) AS NRIC,
Name,
Contact,
Salary,
CONCAT(SUBSTRING(DBS_Account, 1, 3), '-XXXXX-X') AS DBS_Account
FROM yourTable;

mysql rand function - https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
using substring and concat
SELECT CONCAT(SUBSTRING(RAND(),3,5),'-',SUBSTRING(RAND(),3,1))
will give something like 40033-8
then concat with substring
set #a ='038-12645-6';
SELECT CONCAT(substring_index(#a,'-',1),'-',SUBSTRING(RAND(),3,5),'-',SUBSTRING(RAND(),3,1));
'038-63475-5'

Related

SQL SUBSTRING in WHERE condition

create table numbers (number varchar(10));
insert into numbers (number) values
('1234123452'),
('5532003644'),
('1122330505'),
('1103220311'),
('1103000011'),
('1103020012');
Query:-
SELECT * FROM numbers
WHERE SUBSTRING(Number,1,4) = SUBSTRING(Number,5,8)
Result:-
There are no results to be displayed.
Expected Result:
1234123452
The third argument to SUBSTRING() is the length, not the ending position. So it should be:
SELECT * FROM numbers
WHERE SUBSTRING(Number,1,4) = SUBSTRING(Number,5,4)
You could take advantage of REGEXP_LIKE here, assuming you are using MySQL 8+:
SELECT *
FROM numbers
WHERE REGEXP_LIKE(Number, '^(.{4})\\1';
The pattern ^(.{4})\\1 matches and captures the first four characters, then asserts that these same characters appear immediately afterward.

SELECT/LOCATE Query Outputting Incorrect Results

I have a column (kills) with values separated by colons as such: 0;2;0. I wanted to select whatever the middle digit may be, and came up with this query:
SELECT RIGHT(kills, LOCATE(';', kills) - 1)-LEFT(kills, LOCATE(';', kills) - 1) FROM stats WHERE id='135' AND LOCATE(';', kills) > 0;
(I'm aware the where clause is specific, it was for debug purposes. It would realistically be set to a variable which outputs the row id)
It works perfectly fine when the results all have the same decimal place such as 1;2;3 or 10;20;30, but returns wild results when the case is otherwise, such as 1;20;30 or 10;20;3.
1;20;21 outputs 0. -- 10;20;2 outputs -10.
2;20;21 outputs -1. -- 20;20;2 outputs -20.
9;20;21 outputs -8. -- 90;20;2 outputs -90.
I would like to select the middle value of all of these values even if one value doesn't share the same decimal place.
If you want the middle number of three, then you want the second number. Use substring_index():
select substring_index(substring_index(kills, ';', 2), ';', -1)

Mysql regular expression or function for extracting numbers from a specific string

I have a column that has values of the forms:
AB232/10D20
A232/10D20
232/10D20
How can I extract the three numbers in mysql? I want to get 232, 10 and 20 separately and insert them in other columns.
For example, if the the column containing those values is called original_column, the query I need is something like this:
update mytable
set number_one = something(original_column),
number_two = something2(original_column),
number_three = something3(original_column)
Try the following query using LOCATE and SUBSTRING functions:
UPDATE mytable
SET number_one = SUBSTRING(original_column, LOCATE('/', original_column) - 3, 3),
number_two = SUBSTRING(original_column, LOCATE('/', original_column) + 1, 2),
number_three = SUBSTRING(original_column, -2, 2)
The middle number is easy. The last number and the first number are pretty easy, if we assume that they are always 3 and 2 characters.
update mytable
set number_one = right(substring_index(original_column, '/', 1), 3),
number_two = substring_index(original_column, '/', -1) + 0,
number_three = right(original_column, 2);
There are other tricks you can use if the columns are not exactly those lengths. But in your example, all the values have the same length.
When splitting it using regex, use the group feature. Regex for splitting 3 numbers with non-numeric delimiters (for integers only) would be
([0-9])[^0-9]([0-9])[^0-9]([0-9]*)
Use a regex tester to improve the regex.

Getting all instances of a column when the substr is greater than 1

Ok, I've got a unique identifier, and at one point, these got cloned, along with the rows going with them.
To keep those rows (some of which were legitimate), we took off the last 3 characters of a given id and gave it three new ones.
I want to grab all of the unique identifiers which are identified by a multiple of the truncated id - for example:
ID 1:
123456789
ID 2:
123456888
I'd like to take a look at the substring (which in this case would be 123456), and grab both values that contain it.
This is what I currently have:
select substr(uuid, 1, 33) as substring, uuid
from node
where uuid like concat('', substr(uuid, 1, 33), '%')
and count(substr(uuid, 1, 33)) > 1
However I get "invalid use of the group function". Should I be using group by and having? How would I use them appropriately in this context?
My goal is to grab every item in the uuid field that has a given substring of the uuid field more than one time.
So any uuid that contains a given string that another uuid does (that is, there is a repeating substring in the uuid) should be pulled and displayed.
This query, for example, gives me the substrings that have the uuids that I want, but it doesn't give me the uuids themselves:
select substr(uuid, 1, 33) as substring, uuid from node where uuid like concat('', substr(uuid, 1, 33), '%') group by substring having count(substring) > 1
I want the uuids associated with the substring, as such:
substring:
0e3c1fef-3958-436b-8e2b-0c6f7b7be
uuids:
0e3c1fef-3958-436b-8e2b-0c6f7b7be212
0e3c1fef-3958-436b-8e2b-0c6f7b7be075
0e3c1fef-3958-436b-8e2b-0c6f7b7be981
So basically all of the uuids associated with multiple instances of a substring.
The count for this particular substring would be 3.
Aggregate functions can't be used in the WHERE clause, they can only be used in HAVING.
SELECT uuid
FROM node
WHERE SUBSTR(uuid, 1, 33) IN (
SELECT substr(uuid, 1, 33) as substring
FROM node
GROUP BY substring
HAVING COUNT(*) > 1
)
Another way to write it that might use indexes better is:
SELECT uuid
FROM node AS n
JOIN (SELECT CONCAT(SUBSTR(uuid, 1, 33), '%') AS pattern
FROM node
GROUP BY pattern
HAVING COUNT(*) > 1) AS p
ON n.uuid LIKE p.pattern

How to separate value by using comma my SQL?

My table column has rows like this 1001, 1002, 1003 and so on separated by commas. There may be 1 or more comma separated values in each column. I need the total count of these comma separated values in the table. For example if my table has 2 rows one having 1001, 1002, 1003, 1004 and another with 1001, 1005 the output i should get is 6 i.e. 4+2. Kindly assist
there is no function in mysql to count char occurences. but you can replace every comma with nothing. and then you calculate the difference of lenghts which will give you the number of commas, which is one less than the number of values.
select
( LENGTH(col1) - LENGTH(REPLACE(col1, ',', '')) + 1 )
+ ( LENGTH(col2) - LENGTH(REPLACE(col2, ',', '')) + 1 )
AS valCount
from T;
(didn't test that explicitely but at least something very similar to that will do the job.)
replace()
length()
Try:
SELECT SUM(LEN(ColumnName) - LEN(REPLACE(ColumnName, ',', ''))) FROM TableName
This is one of those tasks that'd be much, much easier in the server-side script accessing your database than the database itself. Assuming you've already assigned the comma-separated strings to an array (where $array[1] is equal to the string from row 1:
$array = array("1001, 1002, 1003, 1004", "1001, 1005"); // assigned from database
foreach($array as $k => $v){
$numbersInString[$k] = count(explode(', ', $v));
}
echo implode(' + ',$numbersInString);
This is possible, with creative solutions (such as that from Raffael1984), in MySQL, but seems to much more easily, and concisely, implemented in PHP.
References:
count().
explode().
implode().
foreach().
Did you try using the count() function? You can specify which rows if you need to.
.row[COUNT(name)]
in your query. What does your table look like? I might be able to help more if I know what it looks like