I have table with values. It is ntext because of ; delimited. Values can be empty, 1 number and numbers delimited by semicolon (as shown)
+-----------+
| room |
+-----------+
| 64 |
+-----------+
| 60008 |
+-----------+
| |
+-----------+
| 127;50047 |
+-----------+
I have this code. Substring is looking for ; and show first value. It is working only where the values are delimited. So how can I change it, that it will show first value when ; and single value also. So from table bellow I will get 64,60008, ,127.
SELECT
T0.U_Scid as 'id',
T3.U_Boarding as 'start',
T3.U_Boarding as 'end',
SUBSTRING(T5.U_Partner, 0, CHARINDEX(';', T5.U_Partner)) AS 'room_id',
CASE WHEN datalength(T5.U_Partner)=0 THEN '9999' ELSE T5.U_Partner END AS 'room_id' ,
CASE WHEN datalength(T5.U_Partner) > 4 THEN T5.U_Partner ELSE '9999' END AS 'partners_id' ,
This is just bonus question. CASE are looking for length of value, if the value is longer than 4 ( 600008 ) write to room_id 9999 and save 600008 to partners_id. If it is empty write 9999 to room_id.
How to make it works together?.so getting value from T_Partner..save it into temporary table T1.TempRoom ( I suppose ).. so T1.TempRoom (is filled with numbers like 64, ,60008,127) then CASE is checking T1.TempRoom for values and save it into room_id and partners_id.
Am I right?
Here is a simple method:
SUBSTRING(T5.U_Partner, 1, CHARINDEX(';', T5.U_Partner + ';')) AS room_id,
That is, concatenate the semicolon to the argument for CHARINDEX(). That will prevent any error occurring.
In addition, indexing for SUBSTRING() starts at 1, not 0.
And, don't use single quotes for column names. Only use them for string and date literals.
EDIT:
You can always use the verbose form:
(CASE WHEN T5.U_Partner LIKE '%;%'
THEN SUBSTRING(T5.U_Partner, 1, CHARINDEX(';', T5.U_Partner + ';'))
ELSE T5.U_Partner
END) AS room_id
Related
I am trying write a SQL SELECT statement in Snowflake where I need to select a column 'xyz' form table 'a'(select xyz from a). Although, the number in column xyz is formatted into 6,7,8 digits and I want to convert that in select statement itself to 16 digits with leading 0's. I used concat() but since the column contains either 6,7,8 digits I am not able to format it into max 16 digits with leading 0's.
Note: I need it to be in select statement as I cant update the column in the database to 16 digit format.
Example
Input: 123456, 1234567, 12345678
Output should be: 0000000000123456, 0000000001234567, 0000000012345678
Can someone help me out here please. Thanks!
Using TO_VARCHAR with format provided:
SELECT TO_VARCHAR(12345, '0000000000000000');
WITH cte(c) AS (
SELECT * FROM (VALUES (123456), (1234567),(12345678))
)
SELECT c, TO_VARCHAR(c, '0000000000000000') AS result
FROM cte;
Output:
with data(c) as (
select * FROM (
values (12345), (293848238), (284), (239432043223432)
)
)
select lpad(c, 16, '0') as c from data;
+------------------+
| C |
|------------------|
| 0000000000012345 |
| 0000000293848238 |
| 0000000000000284 |
| 0239432043223432 |
+------------------+
If you want dynamic width, or to stick to a form of CONCAT then here are some extra ways.
SELECT column1,
TO_CHAR(column1, '0000000000000000') as fixed_width,
TO_CHAR(column1, REPEAT('0', 16)) as dynamic_width,
RIGHT(REPEAT('0', 16) || column1::text, 16) as another_way,
LPAD(column1, 16, '0')
FROM VALUES
(123456),
(1234567),
(12345678),
(12345.678),
(1234567890123456789)
COLUMN1
FIXED_WIDTH
DYNAMIC_WIDTH
ANOTHER_WAY
LPAD(COLUMN1, 16, '0')
123,456
0000000000123456
0000000000123456
000000123456.000
000000123456.000
1,234,567
0000000001234567
0000000001234567
000001234567.000
000001234567.000
12,345,678
0000000012345678
0000000012345678
000012345678.000
000012345678.000
12,345.678
0000000000012346
0000000000012346
000000012345.678
000000012345.678
1,234,567,890,123,456,789
################
################
890123456789
1234567890123456
the two TO_CHAR/TO_VARCHAR methods don't deal with floating results, where-as the RIGHT version does. But that doesn't handle values that are larger the 16 DP
Using you SQL
So using the SQL you put in your comment, and then using 2 CTE's for fake out some data AND using one of the many answers to your question, we get:
WITH "abc" as (
SELECT * FROM VALUES
(123456),
(1234567)
t(ki)
), "xyz" as (
SELECT * FROM VALUES
(6, 123456),
(7, 1234567)
t(ki_value, piv_id)
)
SELECT DISTINCT
y.kI,
yo.ki_value,
yo.piv_num
FROM "abc" as y
left join (
select
ki_value,
LPAD(piv_id, 16, '0') as piv_num
--concat('0000000000',piv_id) as piv_num
from "xyz"
) as yo on y.KI = yo.piv_num
WHERE y.KI in (123456,1234567)
this gives:
KI |KI_VALUE |PIV_NUM
--|--|--
123,456 |6 |0000000000123456
1,234,567 |7 |0000000001234567
So this "works" but as your SQL is written, it's really bad. The WHERE statement is checking the values are numbers and are in the range, why on earth are you want to string pad numbers as TEXT with however many number of zeros in front, because you should leave them as numbers.
I have a database field with several values separated by newline.
Eg-(can be more than 3 also)
A
B
C
I want to perform an operation to modify these values by adding tags from front and end.
i.e the previous 3 values should need to be turned into
<Test>A</Test>
<Test>B</Test>
<Test>C</Test>
Is there any possible query operation in Oracle SQL to perform such an operation?
Just replace the start and end of each string with the XML tags using a multi-line match parameter of the regular expression:
SELECT REGEXP_REPLACE(
REGEXP_REPLACE( value, '^', '<Test>', 1, 0, 'm' ),
'$', '</Test>', 1, 0, 'm'
) AS replaced_value
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name ( value ) AS
SELECT 'A
B
C' FROM DUAL;
Outputs:
| REPLACED_VALUE |
| :------------- |
| <Test>A</Test> |
| <Test>B</Test> |
| <Test>C</Test> |
db<>fiddle here
You can use normal replace function as follows:
Select '<test>'
|| replace(your_column,chr(10),'</test>'||chr(10)||'<test>')
|| '</test>'
From your_table;
It will be faster than its regexp_replace function.
Db<>fiddle
I have a column "A" which contains numbers for example- 0001, 0002, 0003
the same column "A" also contains some alphabets and special characters in some of the rows for example - connn, cco*jjj, hhhhhh11111 etc.
I want to replace these alphabets and special characters rows with blank values and only want to keep the rows containing the number.
which regex expression I can use here?
If you want to extract numbers from these values (even if they end or start with non digits), you may use something like this:
create table testing ( A varchar ) as select *
from values ('123'),('aaa123'),('3343'),('aaaa');
select REGEXP_SUBSTR( A, '\\D*(\\d+)\\D*', 1, 1, 'e', 1 ) res
from testing;
+------+
| RES |
+------+
| 123 |
| 123 |
| 3343 |
| NULL |
+------+
I understand that you want to set to null all values that do not contain digits only.
If so, you can use try_to_decimal():
update mytable
set a = null
where a try_to_decimal(a) is null
Or a regexp match:
update mytable
set a = null
where a rlike '[^0-9]'
I have data stored in table's column and it has a line break in the data. When I count the length of the string it returns me the count just fine. I want to make some changes and take the line break as 2 characters so if the data in table is something like this.
This
That
This should return length as 10 instead it is returning 9 for now which is understandable but I was to count the length of line break as 2 characters. So if there are 2 line breaks in data it will count them as 4 characters.
How can I achieve this ?
I want to use this in SUBSTR(COL, 1, 7)
By counting line break as 2 character it should return data like this
This
T
Hope someone can help
Just replace new line in the string with 2 characters, for example 'xx', before counting string length. More info on how to replace new lines in Oracle: Oracle REPLACE() function isn't handling carriage-returns & line-feeds
Update your value to have a line feed character before the carriage return character.
So if you have the table:
CREATE TABLE test_data ( value VARCHAR2(20) );
INSERT INTO test_data ( value ) VALUES ( 'This
That' );
Then you can insert the LF before the CR:
UPDATE test_data
SET value = REPLACE( value, CHR(10), CHR(13) || CHR(10) )
WHERE INSTR( value, CHR(10) ) > 0
Then your query:
SELECT SUBSTR( value, 1, 7 ) FROM test_data;
Outputs:
| SUBSTR(VALUE,1,7) |
| :---------------- |
| This |
| T |
db<>fiddle here
I have a table table1 with the following data
+----------------+
| model |
+----------------+
| a45/ a45m;aa45 |
| b34/b34m |
| c23;c23m/ cc23 |
+----------------+
I'm trying to clean up the model field with certain rules, such as
grab all characters before the first ;
from 1, grab all character before the first /
So I do the following in netezza for step 1
SELECT
SUBSTR(model, 1, STRPOS(model, ';')-1) AS model_clean
FROM table1
;
This throws error ERROR [42000] Syntax error or access violation. Any ideas why this is happening, does the character ; need to be escaped ?
One thing to note is that When I look for the space character as following, there is no error.
SELECT
SUBSTR(model, 1, STRPOS(model, ' ')-1) AS model_clean
FROM table1
;
Also is there a way to get step 2 also done in this same select statement ?
Expected output
+----------------+
| model_clean |
+----------------+
| a45 |
| b34 |
| c23 |
+----------------+
It fails because not all columns have semicolons, so strpos() returns 0. You can fix this just by adding a semicolon:
SELECT SUBSTR(model, 1, STRPOS(model || ';', ';') - 1) AS model_clean
Your query fails when you try to do substring with an invalid position, the result of strpos wich didn't found the semicolon.
You can use case statement to avoid calculate invalid position
Here are an example of SQLServer syntaxe ( charindex and strpos have reversed parameter order, up to you to reduce the query) http://sqlfiddle.com/#!18/55a6e/25
WITH step1
AS ( SELECT CASE
WHEN CHARINDEX(';', model) > 0 THEN SUBSTRING(model, 1, CHARINDEX(';', model) - 1)
ELSE model
END AS model
FROM table1 ),
step2
AS ( SELECT CASE
WHEN CHARINDEX('/', model) > 0 THEN SUBSTRING(model, 1, CHARINDEX('/', model) - 1)
ELSE model
END AS model
FROM step1 )
SELECT *
FROM step2;