Get count of zeros in an integer using MySQL - mysql

Let's say I have an integer value in MySQL (10090). I need to count all occurrences of the zero digit in that number. So for the previous case it would return 3:
select count_zeros(number) from dual;
-- when number = 10090, it return 3
-- when number = 10000, it return 4
How can I do that the fastest way using a MySQL query?

You can compare the string length with and without the character you want to count.
Solution using LENGTH
-- 0 in 10090: 3
-- 0 in 10000: 4
SELECT
(LENGTH(number) - LENGTH(REPLACE(number, '0', ''))) AS char_count
FROM dual;
A better and safer solution is to use the CHAR_LENGTH function instead of the LENGTH function. With CHAR_LENGTH function you can also count multi-byte characters (like §).
Solution using CHAR_LENGTH
-- § in 100§0: 1
SELECT
(CHAR_LENGTH(number) - CHAR_LENGTH(REPLACE(number, '§', ''))) AS char_count
FROM dual;
You can also extend the above solution to count for a string value using multiple characters.
-- 12 in 10120012: 2
SELECT number,
FLOOR((CHAR_LENGTH(number) - CHAR_LENGTH(REPLACE(number, '12', ''))) / CHAR_LENGTH('12')) AS str_count
FROM dual;
demo on dbfiddle.uk
On MySQL you can create a function to use the above logic on a simpler way:
CREATE FUNCTION GetStringCount(strValue VARCHAR(255), strSearchValue VARCHAR(255))
RETURNS INT DETERMINISTIC NO SQL
RETURN FLOOR((CHAR_LENGTH(strValue) - CHAR_LENGTH(REPLACE(strValue, strSearchValue, ''))) / CHAR_LENGTH(strSearchValue));
You can use this new function GetStringCount like this:
-- example to count non-multi-byte character (here 0).
-- 0 in 10090: 3
-- 0 in 10000: 4
SELECT number, GetStringCount(number, '0') AS strCount
FROM dual;
-- example to count multi-byte character (here §).
-- § in 100§0: 1
SELECT number, GetStringCount(number, '§') AS strCount
FROM dual;
-- example to count a string with multiple characters.
-- 12 in 10120012: 2
SELECT number, GetStringCount(number, '12') AS strCount
FROM dual;

I think the first thing to be done is, casting those integer values to string.
https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast
Then find occurences of a certain char
https://lists.mysql.com/mysql/215049
mysql> create table numbers(x int);
Query OK, 0 rows affected (0,38 sec)
mysql> select * from numbers;
+-----------+
| x |
+-----------+
| 123000 |
| 1300 |
| 135600 |
| 135623400 |
| 13560 |
| 135160 |
| 13514560 |
| 1351120 |
| 13512310 |
+-----------+
9 rows in set (0,00 sec)
Find occurences of zero
mysql> select x, round((length(cast(x as char(11))) - length( replace( cast( x as char(11) ), "0", "" ) ))/length("0")) as str_x from numbers limit 5;
+-----------+-------+
| x | str_x |
+-----------+-------+
| 123000 | 3 |
| 1300 | 2 |
| 135600 | 2 |
| 135623400 | 2 |
| 13560 | 1 |
+-----------+-------+
5 rows in set (0,00 sec)
Find thirteens
mysql> select x, round((length(cast(x as char(11))) - length( replace( cast( x as char(11) ), "13", "" ) ))/length("13")) as str_x from numbers;
+-----------+-------+
| x | str_x |
+-----------+-------+
| 123000 | 0 |
| 1300 | 1 |
| 135600 | 1 |
| 135623400 | 1 |
| 13560 | 1 |
| 135160 | 1 |
| 13514560 | 1 |
| 1351120 | 1 |
| 13512310 | 1 |
| 132134534 | 2 |
+-----------+-------+
10 rows in set (0,00 sec)
mysql>

Related

Using code to increment values in a column

I am trying to use a simple code to increment only the values in the “chat_id” column of a table.
For the table lz_chat_archive_dup1, the column “chat_id” is has empty strings (no values). This is the partial excerpt of the table :
mysql> select chat_id, fullname from lz_chat_archive_dup1 LIMIT 5;
+---------+--------------+
| chat_id | fullname |
+---------+--------------+
| | Yw |
| | Shah |
| | Sunny Duhel |
| | Leong Zi Yin |
| | Mohd Nasir |
+---------+--------------+
5 rows in set (0.00 sec)
I tried to insert a value for the name “Yw” like this and it worked :
mysql> UPDATE lz_chat_archive_dup1 SET chat_id = '383933' where fullname = 'Yw';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
So now the table is like this :
mysql> select chat_id, fullname from lz_chat_archive_dup1 LIMIT 5;
+---------+--------------+
| chat_id | fullname |
+---------+--------------+
| 383933 | Yw |
| | Shah |
| | Sunny Duhel |
| | Leong Zi Yin |
| | Mohd Nasir |
+---------+--------------+
5 rows in set (0.00 sec)
However, the number of rows in this table is 2589, and for me to do it one by one is tedious and time consuming :
mysql> select count(*) from lz_chat_archive_dup1;
+----------+
| count(*) |
+----------+
| 2589 |
+----------+
1 row in set (0.00 sec)
I thought I could use a code something like this to update/increment only that one column, but I don’t think this is the correct syntax for MySQL. Can you please help to correct the code to customize it to work in my situation :
DECLARE #counter int
SET #counter = 383933
UPDATE #lz_chat_archive_dup1
SET #counter = counter = #counter + 1
So with this code, what I am trying to achieve is increment the chat_id column so that the next value is always 1 integer higher than the previous one. So the first row is 383933, the next one should be 383934, 383935, 383936,…etc etc.
The table has > 2000 rows, so this is an excerpt of it :
mysql> select time, endtime, chat_id from lz_chat_archive_dup1 LIMIT 20;
+------------+------------+---------+
| time | endtime | chat_id |
+------------+------------+---------+
| 1594948770 | 1594948928 | 383933 |
| 1594950285 | 1594950542 | |
| 1594950708 | 1594951085 | |
| 1594953554 | 1594955581 | |
| 1594955956 | 1594956551 | |
| 1595215646 | 1595218410 | |
| 1595215648 | 1595216044 | |
| 1595216110 | 1595216138 | |
| 1595220816 | 1595221144 | |
| 1595221046 | 1595221584 | |
| 1595221448 | 1595221505 | |
| 1595222302 | 1595222653 | |
| 1595236468 | 1595236848 | |
| 1595236954 | 1595237033 | |
| 1595293418 | 1595293589 | |
| 1595303280 | 1595304388 | |
| 1595303410 | 1595303822 | |
| 1595303675 | 1595303986 | |
| 1595304153 | 1595306613 | |
| 1595304878 | 1595304995 | |
+------------+------------+---------+
20 rows in set (0.00 sec)
mysql>
Here is an approach using a user variable:
set #rn = 383933;
update #lz_chat_archive_dup1
set chat_id = (select #rn := #rn + 1)
order by name;
This will assign an incrementingn number to each row, following the alphabetical order of name. If there are ties, it is undefined which name will get which number (a reason why you should have a primary key column in your table).
Assuming the names are unique, you could use a join:
update lz_chat_archive_dup1 cad join
(select cad2.*, row_number() over () as seqnum
from lz_chat_archive_dup1 cad2
) cad2
on cad2.name = cad.name
set count = seqnum + 383933;
I think this might be the recommended approach in MySQL 8+. (The statement on the deprecation of variables is a little vague on whether it would apply to UPDATE.)
You can also use variables. The problem with your statement is:
SET #counter = counter = #counter + 1
This is not even setting the column in the table! It is setting a variable. Use := to set parameters. And I strongly recommend parentheses. So, you can do:
DECLARE #counter int;
SET #counter = 383933;
UPDATE #lz_chat_archive_dup1
SET counter = (#counter := #counter + 1);
Or, in a single statement:
UPDATE #lz_chat_archive_dup1 cad CROSS JOIN
(SELECT #counter := 383933) params
SET cad.counter = (#counter := #counter + 1);
If you can live with numbers starting from 1, following the alphabetic order of your fullname column, you can try with a helper table to run the update:
CREATE TABLE updtab
AS
SELECT
ROW_NUMBER() OVER(ORDER BY fullname) AS chat_id
, fullname
FROM lz_chat_archive_dup1;
Then , run the update:
UPDATE lz_chat_archive_dup1
SET chat_id = (
SELECT chat_id
FROM updtab
WHERE updtab.fullname=lz_chat_archive_dup1.fullname
)
;

MYSQL - Count items separated by comma or not

I have a tinytext field which can contain 3 differents value formatted as followed:
NULL
"X" or "Y" (where X and Y can be any number)
"A,B,C,D" (where A, B, C and D can be any number)
I want to query the table and count the number of items separated or not with a comma.
For example with these lines:
42
NULL
42,56,99
24,10090
Then the expected count would be 6.
I can't find the correct query.
Okay here's the test data:
mysql> create table t (f tinytext);
mysql> insert into t values ('42'), (null), ('42,56,99'), ('24,10090');
mysql> select * from t;
+----------+
| f |
+----------+
| 42 |
| NULL |
| 42,56,99 |
| 24,10090 |
+----------+
You can calculate how many numbers in the string as the difference in the length of the string and the string with commas removed (add 1 for the first number in the list).
mysql> select f, length(f), length(replace(f,',','')), 1+ length(f)-length(replace(f,',','')) from t;
+----------+-----------+---------------------------+----------------------------------------+
| f | length(f) | length(replace(f,',','')) | 1+ length(f)-length(replace(f,',','')) |
+----------+-----------+---------------------------+----------------------------------------+
| 42 | 2 | 2 | 1 |
| NULL | NULL | NULL | NULL |
| 42,56,99 | 8 | 6 | 3 |
| 24,10090 | 8 | 7 | 2 |
+----------+-----------+---------------------------+----------------------------------------+
So then use SUM() to get the total. SUM() ignores NULLs.
mysql> select sum(1+length(f)-length(replace(f,',',''))) from t;
+--------------------------------------------+
| sum(1+length(f)-length(replace(f,',',''))) |
+--------------------------------------------+
| 6 |
+--------------------------------------------+
This would be easier if you don't store comma-separated lists in a string.

Generate 6 digit random number in mysql

I want to generate random 6 digit number in mysql but sometime it generate only 5 digit.
UPDATE member SET updates = FLOOR(RAND() * 999999)
If the problem is that you are missing leading zeros, you can left pad with spaces:
UPDATE member
SET updates = LPAD(FLOOR(RAND() * 999999.99), 6, '0');
I hope you understand that "random" means "random" and different rows can get the same value.
This generate 6 digit number exactly:
UPDATE member SET updates = FLOOR((RAND() * (999999-100000+1))+100000);
You can generate random 6 digit number in mysql
UPDATE member SET updates = LPAD(FLOOR(RAND() * 999999.99), 6, '0');
+--------+
| Value |
+--------+
| 499540 |
| 550607 |
| 254419 |
| 620272 |
| 338104 |
| 829705 |
+--------+
or you can also random number generate in mysql 1 to 200 in increment form. you can change in place of 200 to **** as you like
UPDATE member SET updates = FLOOR(1 + (RAND() * 200));
+--------+
| Value |
+--------+
| 1 |
| 180 |
| 50 |
| 85 |
| 33 |
| 165 |
+--------+

Changing the fractions in sql

I have fractions as string in my database and it is currently like this:
3/8
I want to change to this:
<sup>3</sup>⁄<sub>8</sub>
I have many fractions like this. How do I change them at one shot in SQL? I know I need to use Regular Expressions but not sure how to use it.
What I have tried so far:
UPDATE question_table
SET `option` = Replace(`option`, ?? ,??)
WHERE `option` LIKE '%/%'
Not sure what to fill up in ??.
SELECT * FROM strings;
+--------+
| string |
+--------+
| 19/32 |
| 3/8 |
| 5/16 |
+--------+
SELECT *
, CONCAT('<sup>'
, SUBSTRING_INDEX(string,'/',1)
, '</sup>⁄<sub>'
, SUBSTRING_INDEX(string,'/',-1)
,'</sub>'
) x
FROM strings;
+--------+-----------------------------------+
| string | x |
+--------+-----------------------------------+
| 19/32 | <sup>19</sup>⁄<sub>32</sub> |
| 3/8 | <sup>3</sup>⁄<sub>8</sub> |
| 5/16 | <sup>5</sup>⁄<sub>16</sub> |
+--------+-----------------------------------+
UPDATE strings
SET string = CONCAT('<sup>'
, SUBSTRING_INDEX(string,'/',1)
, '</sup>⁄<sub>'
, SUBSTRING_INDEX(string,'/',-1)
, '</sub>'
);
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
SELECT * FROM strings;
+-----------------------------------+
| string |
+-----------------------------------+
| <sup>19</sup>⁄<sub>32</sub> |
| <sup>3</sup>⁄<sub>8</sub> |
| <sup>5</sup>⁄<sub>16</sub> |
+-----------------------------------+

Approximate selection between decimal values in perl-DBI

I was developed database table by using this query
create table test(
id varchar(10),
alpha varchar(1000),
marks decimal(10,4)
);
In the marks should use decimal datatypes.
marks column
1100.2523
1100.2722
733.8375
1192.257
587.6248
392.0859
I should use to select query
select * from test where marks="1100.2625";
and
select * from test where marks="392.0252";
The output is Empty set (0.00 sec)
Expected Output is
1100.2523 1100.2722 and 392.0859 this rows.
If possible to select between decimal range.?
This is usually not possible using the query and for that you need to define a benchmark for the approximation.
Now if you have a bench mark set for the approximation and lets say its something as
If the marks and compared value is same rounding to first decimal point then its a match.
If the after rounding to first decimal point both marks and input and taking the difference the value is 1 or -1 then its a match.
Using the above benchmark it could done.
Consider the following table
mysql> select * from test ;
+------+-------+-----------+
| id | alpha | marks |
+------+-------+-----------+
| 1 | aa | 1100.2523 |
| 2 | bb | 1100.2722 |
| 3 | cc | 392.0859 |
+------+-------+-----------+
mysql> select * from test where round(marks,1) = round(1100.2625,1);
+------+-------+-----------+
| id | alpha | marks |
+------+-------+-----------+
| 1 | aa | 1100.2523 |
| 2 | bb | 1100.2722 |
+------+-------+-----------+
mysql> select * from test
where round(marks,1) = round(392.0252,1)
or round(marks,1) - round(392.0252,1) = 0.1
or round(marks,1) - round(392.0252,1) = -0.1;
+------+-------+----------+
| id | alpha | marks |
+------+-------+----------+
| 3 | cc | 392.0859 |
+------+-------+----------+