how can I convert a number to a string, extract each digit, cast it again to integers, and add them all together (e.g. 1+2+3+4+5+6) in SQL? - sql

I'm thinking I have to create a view that stores the cast as text and I have to utilize the substring function in sql but I'm a little lost. Any help would be greatly appreciated?

You can convert a string to rows using unnest() and string_to_array() and then add the digits using sum()
select sum(digit::int)
from unnest(string_to_array(12345::text, null)) as x(digit)

You can format the number
select to_char(12345, '0+0+0+0+0+0+0');
to_char
----------------
0+0+1+2+3+4+5
Inside a function, you can run this statement as a dynamic query to get the result
EXECUTE 'SELECT ' || to_char(12345, '0+0+0+0+0+0+0');

You can use a recursive CTE:
WITH RECURSIVE qsum AS (
SELECT 123456 AS num,
0 AS sum
UNION ALL
SELECT num / 10,
sum + num % 10
FROM qsum
WHERE num > 0
)
SELECT max(sum)
FROM qsum;
max
═════
21
(1 row)

You can get there with regexp_split_to_table, using ?!^ to split on every character.
regexp_split_to_table(cast(<your column> as text),'(?!^)') as s
Here's a simple Fiddle

You can shred the string to rows, then sum:
SELECT SUM(CAST(n as INTEGER))
FROM regexp_split_to_table('01234567', '') as n
But this sort of string math is probably a better fit for calling code. If you are trying to validate new records, consider doing it outside of the DB.

Related

How to sort string with numbers numerically in SQL?

this is how it is currently sorted:
CRI-SU1
CRI-SU10
CRI-SU11
CRI-SU2
CRI-SU3
CRI-SU4
CRI-SU5
CRI-SU6
CRI-SU7
CRI-SU8
CRI-SU9
I wanted it to be sorted numerically like:
CRI-SU1
CRI-SU2
CRI-SU3
CRI-SU4
CRI-SU5
CRI-SU6
CRI-SU7
CRI-SU8
CRI-SU9
CRI-SU10
CRI-SU11
How do you sort it in SQL?
this is my sql statement...
SELECT systemUnitID FROM systemUnit ORDER BY systemUnitID
If the prefix always reads "CRI-SU", you can try to replace it with the empty string by using replace(). Then cast the result to an integer with cast() and order by the casted value. This should work in many DBMS.
SELECT systemunitid
FROM systemunit
ORDER BY cast(replace(systemunitid, 'CRI-SU', '') AS integer);
SELECT systemUnitID
FROM systemUnit
ORDER BY CAST(REPLACE(systemUnitID, 'CRI-SU', '') As int)

Concatenate & Trim String

Can anyone help me, I have a problem regarding on how can I get the below result of data. refer to below sample data. So the logic for this is first I want delete the letters before the number and if i get that same thing goes on , I will delete the numbers before the letter so I can get my desired result.
Table:
SALV3000640PIX32BLU
SALV3334470A9CARBONGRY
TP3000620PIXL128BLK
Desired Output:
PIX32BLU
A9CARBONGRY
PIXL128BLK
You need to use a combination of the SUBSTRING and PATINDEX Functions
SELECT
SUBSTRING(SUBSTRING(fielda,PATINDEX('%[^a-z]%',fielda),99),PATINDEX('%[^0-9]%',SUBSTRING(fielda,PATINDEX('%[^a-z]%',fielda),99)),99) AS youroutput
FROM yourtable
Input
yourtable
fielda
SALV3000640PIX32BLU
SALV3334470A9CARBONGRY
TP3000620PIXL128BLK
Output
youroutput
PIX32BLU
A9CARBONGRY
PIXL128BLK
SQL Fiddle:http://sqlfiddle.com/#!6/5722b6/29/0
To do this you can use
PATINDEX('%[0-9]%',FieldName)
which will give you the position of the first number, then trim off any letters before this using SUBSTRING or other string functions. (You need to trim away the first letters before continuing with the next step because unlike CHARINDEX there is no starting point parameter in the PATINDEX function).
Then on the remaining string use
PATINDEX('%[a-z]%',FieldName)
to find the position of the first letter in the remaining string. Now trim off the numbers in front using SUBSTRING etc.
You may find this other solution helpful
SQL to find first non-numeric character in a string
Try this it may helps you
;With cte (Data)
AS
(
SELECT 'SALV3000640PIX32BLU' UNION ALL
SELECT 'SALV3334470A9CARBONGRY' UNION ALL
SELECT 'SALV3334470A9CARBONGRY' UNION ALL
SELECT 'SALV3334470B9CARBONGRY' UNION ALL
SELECT 'SALV3334470D9CARBONGRY' UNION ALL
SELECT 'TP3000620PIXL128BLK'
)
SELECT * , CASE WHEN CHARINDEX('PIX',Data)>0 THEN SUBSTRING(Data,CHARINDEX('PIX',Data),LEN(Data))
WHEN CHARINDEX('A9C',Data)>0 THEN SUBSTRING(Data,CHARINDEX('A9C',Data),LEN(Data))
ELSE NULL END AS DesiredResult FROM cte
Result
Data DesiredResult
-------------------------------------
SALV3000640PIX32BLU PIX32BLU
SALV3334470A9CARBONGRY A9CARBONGRY
SALV3334470A9CARBONGRY A9CARBONGRY
SALV3334470B9CARBONGRY NULL
SALV3334470D9CARBONGRY NULL
TP3000620PIXL128BLK PIXL128BLK

SQL Summing digits of a number

i'm using presto. I have an ID field which is numeric. I want a column that adds up the digits within the id. So if ID=1234, I want a column that outputs 10 i.e 1+2+3+4.
I could use substring to extract each digit and sum it but is there a function I can use or simpler way?
You can combine regexp_extract_all from #akuhn's answer with lambda support recently added to Presto. That way you don't need to unnest. The code would be really self explanatory if not the need for cast to and from varchar:
presto> select
reduce(
regexp_extract_all(cast(x as varchar), '\d'), -- split into digits array
0, -- initial reduction element
(s, x) -> s + cast(x as integer), -- reduction function
s -> s -- finalization
) sum_of_digits
from (values 1234) t(x);
sum_of_digits
---------------
10
(1 row)
If I'm reading your question correctly you want to avoid having to hardcode a substring grab for each numeral in the ID, like substring (ID,1,1) + substring (ID,2,1) + ...substring (ID,n,1). Which is inelegant and only works if all your ID values are the same length anyway.
What you can do instead is use a recursive CTE. Doing it this way works for ID fields with variable value lengths too.
Disclaimer: This does still technically use substring, but it does not do the clumsy hardcode grab
WITH recur (ID, place, ID_sum)
AS
(
SELECT ID, 1 , CAST(substring(CAST(ID as varchar),1,1) as int)
FROM SO_rbase
UNION ALL
SELECT ID, place + 1, ID_sum + substring(CAST(ID as varchar),place+1,1)
FROM recur
WHERE len(ID) >= place + 1
)
SELECT ID, max(ID_SUM) as ID_sum
FROM recur
GROUP BY ID
First use REGEXP_EXTRACT_ALL to split the string. Then use CROSS JOIN UNNEST GROUP BY to group the extracted digits by their number and sum over them.
Here,
WITH my_table AS (SELECT * FROM (VALUES ('12345'), ('42'), ('789')) AS a (num))
SELECT
num,
SUM(CAST(digit AS BIGINT))
FROM
my_table
CROSS JOIN
UNNEST(REGEXP_EXTRACT_ALL(num,'\d')) AS b (digit)
GROUP BY
num
;

PostgreSQL count number of times substring occurs in text

I'm writing a PostgreSQL function to count the number of times a particular text substring occurs in another piece of text. For example, calling count('foobarbaz', 'ba') should return 2.
I understand that to test whether the substring occurs, I use a condition similar to the below:
WHERE 'foobarbaz' like '%ba%'
However, I need it to return 2 for the number of times 'ba' occurs. How can I proceed?
Thanks in advance for your help.
I would highly suggest checking out this answer I posted to "How do you count the occurrences of an anchored string using PostgreSQL?". The chosen answer was shown to be massively slower than an adapted version of regexp_replace(). The overhead of creating the rows, and the running the aggregate is just simply too high.
The fastest way to do this is as follows...
SELECT
(length(str) - length(replace(str, replacestr, '')) )::int
/ length(replacestr)
FROM ( VALUES
('foobarbaz', 'ba')
) AS t(str, replacestr);
Here we
Take the length of the string, L1
Subtract from L1 the length of the string with all of the replacements removed L2 to get L3 the difference in string length.
Divide L3 by the length of the replacement to get the occurrences
For comparison that's about five times faster than the method of using regexp_matches() which looks like this.
SELECT count(*)
FROM ( VALUES
('foobarbaz', 'ba')
) AS t(str, replacestr)
CROSS JOIN LATERAL regexp_matches(str, replacestr, 'g');
How about use a regular expression:
SELECT count(*)
FROM regexp_matches('foobarbaz', 'ba', 'g');
The 'g' flag repeats multiple matches on a string (not just the first).
There is a
str_count( src, occurence )
function based on
SELECT (length( str ) - length(replace( str, occurrence, '' ))) / length( occurence )
and a
str_countm( src, regexp )
based on the #MikeT-mentioned
SELECT count(*) FROM regexp_matches( str, regexp, 'g')
available here: postgres-utils
Try with:
SELECT array_length (string_to_array ('1524215121518546516323203210856879', '1'), 1) - 1
--RESULT: 7

How to get the byte size of resultset in an SQL query?

Is it possible to get the size in bytes of the results of an sql query in MySQL?
For example:
select * from sometable;
ths returns 10000 rows. I don't want the rows but the size of the resultset in bytes. Is it possible?
select sum(row_size)
from (
select
char_length(column1)+
char_length(column2)+
char_length(column3)+
char_length(column4) ... <-- repeat for all columns
as row_size
from your_table
) as tbl1;
char_length for enum, set might not accurate, please take note
To build on Angelin's solution, if your data contains nulls, you'll want to add IFNULL to each column:
select sum(
ifnull(char_length(column1), 0) +
ifnull(char_length(column2), 0) +
ifnull(char_length(column3), 0) +
ifnull(char_length(column4), 0) ... <-- repeat for all columns
)
from your_table
simplify :
select sum(char_length(column1)+
char_length(column2)+
char_length(column3)+
char_length(column4) ... )<-- repeat for all columns
from your_table
You need to add IFNULL() to each column as #futilerebel has mentioned
CHAR_LENGTH() gets number of characters if unicode will be more bytes - use LENGTH() for number of bytes:https://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_length