I am creating new column based on right most values from existing values
ABP-1-3-3
CBP-1-10-12-14
Expoected values for new column i am able to read from left, Values i am getting
-3
14
enter image description here
How can i modify my below code with regexp replace to remove any - ?
SUBSTR(TEST, -2, INSTR(TEST, '-')-1) AS TEST2,
Try this:
with test as
( select 'CBP-1-10-12-14' v1 from dual
union
select 'ABP-1-3-3' v1 from dual
)
select regexp_substr( v1 , '[0-9]*$' )
from test
Also take a look at https://regex101.com/r/bS7hF5/1 . It is a neat site. Put in your regex string, and it will "translate" it to human-readable description.
Related
I'm trying to insert data into a table and one of my columns is coming back null. The columns I sum are working fine, but the one I count is returning null with the insert into command followed by select. When I eliminate insert into, and just run my select statement I get the result I need. What am I doing wrong?
`
INSERT INTO DAILY_TOTALS(TIME_FRAME,
VIDEO,
DATA,
VOICE,
PREV_VIDEO,
PREV_DATA,
PREV_VOICE,
VIDEO_REVENUE,
INTERNET_REVENUE,
PHONE_REVENUE,
OCC_REVENUE,
TOTAL_REVENUE,
ACCOUNTS)
SELECT
D.TIME_FRAME,
D.VIDEO,
D.DATA,
CASE WHEN D.VOICE ='N' THEN 'N' ELSE 'Y' END AS VOICE,
D.PREV_VIDEO,
D.PREV_DATA,
CASE WHEN D.PREV_VOICE = 'N' THEN 'N' ELSE 'Y' END AS PREV_VOICE,
SUM(D.VIDEO_REVENUE) AS VIDEO_REVENUE,
SUM(D.INTERNET_REVENUE) AS INTERNET_REVENUE,
SUM(D.OCC_REVENUE) AS OCC_REVENUE,
SUM(D.TOTAL_REVENUE) AS TOTAL_REVENUE,
COUNT(D.ACCOUNT_NUMBER) AS ACCOUNTS
FROM DAILY D
WHERE D.TIME_FRAME = CURRENT_DATE -1
GROUP BY
D.TIME_FRAME,
D.VIDEO,
D.DATA,
D.VOICE,
D.PREV_VIDEO,
D.PREV_DATA,
D.PREV_VOICE`
Aren't you missing 1 column?
The INSERT statement mentions 13 columns ...but the SELECT only selects 12 columns.
So "COUNT(D.ACCOUNT_NUMBER) AS ACCOUNTS" is being inserted into the TOTAL_REVENUE column. And the ACCOUNTS column in your table is NULL because you haven't specified anything to go in there.
I think this is a pretty simple question but I can't figure out the right search terms to search this. This question is the most similar I could find, but it's the opposite of what I'm trying to do.
I have a query like this :
SELECT * FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since it's an OR, only some of them will give matches from the column.
How can I return the matching LIKE clause with the query itself ? Like this :
SELECT *, (val1 or val2 or val3 - the matched val) FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since the matching is by wildcard "%", I need to get the exact value that got the match.
If the table is this :
name
age
Mike
1
John
2
Michael
3
Milinda
4
And if the query is :
SELECT *, (the matched value) FROM table WHERE name LIKE "Mik%" OR name LIKE "Mic%" OR name LIKE "mia%"
It would return :
name
age
match
Mike
1
Mik
Michael
3
Mic
Is this possible purely with an SQLite query ? I know this can be done later after obtaining the results, but want to remove that redundancy since SQLite will already be matching anyway.
Note: The table is very large. 100,000+ rows. So performance is a big factor to get result as fast as possible. Also the OR conditions can be 5 or 10 or 15+
Create a CTE with all the match strings that you have and join to the table:
WITH cte(match) AS (VALUES ('Mik'), ('Mic'))
SELECT t.*, c.match
FROM tablename t INNER JOIN cte c
ON t.name LIKE c.match || '%'
See the demo.
You may use a case expresssion. See working fiddle below:
Schema (SQLite v3.30)
CREATE TABLE my_table (
`name` VARCHAR(7),
`age` INTEGER
);
INSERT INTO my_table
(`name`, `age`)
VALUES
('Mike', '1'),
('John', '2'),
('Michael', '3'),
('Milinda', '4');
Query #1
SELECT
*,
CASE
WHEN name LIKE "Mik%" THEN "Mik"
WHEN name LIKE "Mic%" THEN "Mic"
WHEN name LIKE "mia%" THEN "mia"
END as matched_value
FROM
my_table
WHERE
name LIKE "Mik%" OR
name LIKE "Mic%" OR
name LIKE "mia%";
name
age
matched_value
Mike
1
Mik
Michael
3
Mic
View on DB Fiddle
I have a column that is stored in ###0.0000000000 format. In a report I'm generating I need it to only show a few significant digits. Problem is the number needed changes based on the product with a default of 2. There's a column in another table that provides the required digits per each product.
I've tried a few things so far but it seems to not like it and throws a syntax error.
Cast(A.Price as Numeric(10,coalesce(B.Sig_Digits,2)))
That threw an error so I tried making the coalesce part a column and aliasing it in case the coalesce broke it, and that didn't work either. Round will take a column as an argument but I don't want it to round. Other than an ugly
case when Sig_digits = 1 then to_char(price,'###0.0') when Sig_digits = 2...
etc. what other options are there? This is a very large report, with 100+ columns and a few million rows so I'd prefer to not do the case when.
Use TO_CHAR with RPAD to add 0s to the end of the format model to the correct number of decimal places:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( value, sig ) AS
SELECT 123.456789, 2 FROM DUAL UNION ALL
SELECT 123456789.123456789, 7 FROM DUAL;
Query 1:
SELECT TO_CHAR( value, RPAD( 'FM999999999990.', sig + 15, '0' ) )
FROM table_name
Results:
| TO_CHAR(VALUE,RPAD('FM999999999990.',SIG+15,'0')) |
|---------------------------------------------------|
| 123.46 |
| 123456789.1234568 |
Am new to sqlite in my learning I come across the subString function so in my exercise, My table name is t1 and my column value is Partha000099 I want to increment by 1 eg., Partha000100 when i try with
SELECT SUBSTR(MAX(ID),6) FROM t1
am getting output as 000099 when I increment by 1 with the below query
SELECT SUBSTR(MAX(ID),6)+1 FROM t1
am getting output as 100, Now my question is how to construct it back as I expect
I tried with the below query,
SELECT 'Partha' || SUBSTR(MAX(ID),6)+1 FROM t1
am getting output as 1. Please some one help me.
While my solution will work, I would advice you against this type of key generation. "SELECT MAX(ID)+1" to generate the next key will be fraught with problems in more concurrent databases and you risk generating duplicate keys in a busy application/system.
It would be better to split the key into two columns, one with the group or name 'Partha', and the other column with an automatically incremented number.
However, having said that, here's how to generate the next key like your example.
You need to:
Split the key into two
Increment the numeric part
Convert it back to a string
Pad it to 6 digits
Here's the SQL that will do that:
SELECT SUBSTR(ID, 1, 6) || SUBSTR('000000' || (SUBSTR(MAX(ID), 7)+1), -6) FROM t1;
To pad it to 6 digits, I prepend 6 zeroes, then grab the last 6 digits from the resulting string with this type of expression
SUBSTR(x, -6)
The reason why you got 1 was that your expression was grouped like this:
SELECT .... + 1
And the .... part, your string concatenation, was then attempted converted to a number, which resulted in 0, thus 0+1 gives 1.
To get the unpadded result you could've just added some parenthesis:
SELECT 'Partha' || (SUBSTR(MAX(ID),6)+1) FROM t1
^ ^
This, however, would also be wrong as it would return Partha1, and that is because SUBSTR(..., 6) grabs the 6th character and onwards and the 6th character is the final a in Partha, so to get Partha100 you would need this:
SELECT 'Partha' || (SUBSTR(MAX(ID),7)+1) FROM t1
^
Hi I have a table with 2 columns with range, so for e.g If Range Start = ABC1/000/0/0000 and Range END = ABC1/000/0/1022 .
I have to get all the values between this range and then join this with another table. Can you let me know how can I get all the values in DUAL table. I am using Oracle 11g.
Basically I need to make a list with first value as ABC1/000/0/0000 second as ABC1/000/0/0001 till ABC1/000/0/1022.
I have no idea what you mean by "storing values temporarily in DUAL". DUAL is a singe column table with a single value!
However, something like this might be what you want. If its not, then perhaps you could elaborate on your problem a little further
select blah
from another_table
where somekey in
( select blah
from table
where col between <rangeStart> and <rangeEnd>
)
So, it seems you need a few things.
Separate the "last value" from a slash-separated string, such as
ABC1/000/0/0000. It is best to do this with standard substr() and
instr() functions, not with regular expressions (for faster
execution). In instr() we can use a negative argument for
occurrence, to indicate "counting from the end of the string".
Something like this:
select range_from, substr(range_from, instr(range_from, '/', -1) + 1
from ...
Actually, you will need to convert this to a number with to_number() for further processing, and you will also need to capture the substring up to the last slash (similar use of substr() and instr(). And you will need to do the same for range_to.
Generate all the numbers from the first value to the last value. This is easily done with a connect by level query (hierarchical query). Some care must be taken since we may need to do this for several input rows (input ranges) at once.
Then put everything back together and use the result in further processing.
I will assume that the range_from string contains at least one slash, that the substring between the last slash and the end of the string represents a non-negative integer in character format, and the range_to similarly contains at least one slash and the substring from the last slash to the end of the string represents a non-negative integer. It is your responsibility to guarantee that this integer is greater than or equal to the one from range_from. In the output I will use the same substring UP TO the last slash as I find in range_from; if the requirement is that range_to must have the same initial substring, it is your responsibility to guarantee that.
I will also assume that the width (number of characters) of the "number" part (the last token in the strings) is not known beforehand and must be calculated in the query.
with
test_data( id, range_from, range_to ) as (
select 1, 'ABC1/000/0/2033', 'ABC1/000/0/2035' from dual union all
select 2, 'xyz/33/200' , 'xyz/33/200' from dual union all
select 3, '300/LMN/000' , '300/LMN/003' from dual
)
-- end of test data; SQL query begins below this line
select id, stub || lpad(to_char(from_nbr + level - 1), len, '0') as val
from (
select id, stub, length(from_str) as len, to_number(from_str) as from_nbr,
to_number(to_str) as to_nbr
from (
select id, substr(range_from, 1, instr(range_from, '/', -1)) as stub,
substr(range_from, instr(range_from, '/', -1) + 1) as from_str,
substr(range_to , instr(range_to , '/', -1) + 1) as to_str
from test_data
)
)
connect by level <= 1 + to_nbr - from_nbr
and prior id = id
and prior sys_guid() is not null
order by id, level -- if needed
;
ID VAL
-- --------------------
1 ABC1/000/0/2033
1 ABC1/000/0/2034
1 ABC1/000/0/2035
2 xyz/33/200
3 300/LMN/000
3 300/LMN/001
3 300/LMN/002
3 300/LMN/003