Snowflake: replacing column values - sql

I have a column that contains both numbers and alphanumeric characters in it. For number values in the column, I am just trying to replace them a different set of numbers. For alphanumeric columns, I am replacing them w/ different letters and numbers. Below are a few values:
select * from t1;
1234
AB145C
678BC
8765
3786CA
Below SQL is not working for some reason:
select col1,
case
when regexp_like(col1,'^[A-Z]+$')
then replace(replace(replace(replace(replace(replace(col1,'A','Z'),'B','Y'),'C','X'),'D','W'),'E','V'),'F','U')
when try_to_number(col1) is not null
then round(to_number(col1)*1.5)
end as col1_replaced
from t1;
what I could be doing wrong here?
Output I'm getting now:
COL1 COL1_REPLACED
1234 1851
AB145C NULL
678BC NULL
8765 13148
3786CA NULL
Desired output:
COL1 COL1_REPLACED
1234 1851
AB145C ZY145X
678BC 678YX
8765 13148
3786CA 3786XZ

All branches of a CASE expression generally need to have the same type. Since the first branch is generating text, therefore the ELSE branch should also do the same. You may cast the ROUND expression to text here:
SELECT col1,
CASE WHEN REGEXP_LIKE(col1, '^[A-Z]+$')
THEN REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(col1, 'A', 'Z'), 'B', 'Y'), 'C', 'X'), 'D', 'W'), 'E', 'V'), 'F', 'U')
WHEN TRY_TO_NUMBER(col1) IS NOT NULL
THEN CAST(ROUND(TO_NUMBER(col1)*1.5) AS VARCHAR(15))
END AS col1_replaced
FROM t1;

Related

log file with insert - how to easly combine column name with inserted value

Has anybody a good solution how to combine column name with inserted value from prepared INSERT SQL?
I have log file. In this log file I have INSERT query. This query contains over 100 columns for example:
INSERT INTO tab
(col_001, col_002, col_003, col_004, col_005, col_006, col_007, col_008, col_009, col_010)
VALUES ('a', 'b', 'c,,,', 'd', 'e', 'f', 'g', 'h', 'i', 'j');
Do you have any ideas how to easly combine column name to value like below:
col_001 = 'a'
col_002 = 'b'
col_003 = 'c,,,'
col_004 = 'd'
col_005 = 'e'
col_006 = 'f'
col_007 = 'g'
col_008 = 'h'
col_009 = 'i'
col_010 = 'j
Lets imagine that I need to find what value will be inserted in column col_067.
Thanks.
Use unpivot for convert column to row
select colname,
colvalue
from tab
unpivot
(
colvalue
for colname in (col_001, col_002, col_003, col_004, col_005, col_006, col_007, col_008, col_009, col_010)
) unpiv;
Demo in db<>fiddle

Concatenate two column values in SQL [duplicate]

This question already has answers here:
SQL Server: Best way to concatenate multiple columns?
(6 answers)
Closed 4 years ago.
I have two columns:
colA colB
a1 b1
NULL b2
a3 NULL
I want to concatenate both columns in a SELECT-query for the following cases:
if value of colA is NULL and colB is NULL return NULL
if value of colA is NULL and colB is NOT NULL return :b1
if value of colA is NOT NULL and colB is NULL return a1
if both values are NOT NULL return a1:b1
How can i select the appropriate values for the cases?
SELECT NULLIF(COALESCE(colA,'')+COALESCE(':'+colB,''), '') FROM myTable
Some explanation:
COALESCE returns the first not-null argument in its argument list. So the first COALESCE turns a null colA into the empty string.
The second COALESCE first prepends a colon to colB -- but if colB is null, attempting to append a string returns NULL! So the result is again the empty string if colB is null, and a colon plus colB if it wasn't.
We append the two COALESCE outputs. We now have everything the OP wanted, except that if both are null, we have the empty string. NULLIF takes care of that -- if its arguments are equal, it returns NULL, otherwise it returns the first argument.
This should do it:
DECLARE #t TABLE (cola VARCHAR(100), colb VARCHAR(100));
INSERT INTO #t VALUES
(NULL, NULL),
('a1', NULL),
(NULL, 'b1'),
('a1', 'b1');
SELECT NULLIF(CONCAT(cola, ':' + colb), '')
FROM #t
NULL
a1
:b1
a1:b1
Keep in mind that:
+ operator yields NULL if any operand is NULL
CONCAT treats NULL values as empty strings
NULLIF is there to handle the special case
;WITH col_data
As
(SELECT cols = CASE WHEN colA IS NOT NULL THEN colA ELSE '' END
+ CASE WHEN colB IS NOT NULL THEN ': '+colB ELSE '' END
FROM CTE
)
SELECT ISNULL(cols, '') from col_data;

SQL - Concat in where clause with IN

I'm trying use IN to query multiple columns. If I use "=", I return rows (see example) but I would like to query multiple.
need query table to return rows A12345 and B98765 but not C00000
column1 | column2
A 12345
B 98765
C 00000
This works
SELECT *
FROM TABLE
WHERE (column1,column2) = ('A',12345)
This does not work.
SELECT *
FROM TABLE
WHERE (column1,column2) IN (('A',12345),('B',98765))
Here is error:
Error: SQL0104N An unexpected token "," was found following ",". Expected tokens may include: "AT MICROSECONDS MICROSECOND SECONDS SECOND MINUTES MINUTE HOURS". SQLSTATE=42601
(State:42601, Native Code: FFFFFF98)
I've tried several variations of parenthesis, commas's, etc and can't get it to work. Is it possible to do this and if so can you provide the syntax.
thanks
DB2 9.7 onwards:
SELECT *
FROM TABLE
WHERE (column1, column2) IN (VALUES ('A', 12345), ('B', 98765))
One solution is to use a temp table:
create table #tmp
(
col1 varchar(2),
col2 int
);
insert into #tmp (col1, col2)
values ('A', 12345), ('B', 98765)
SELECT t.* FROM TABLE t
JOIN #tmp ON #tmp.col1 = t.column1 and #tmp.col2 = t.column2
You haven't stated your RDBMS, but have you tried:
SELECT * FROM TABLE
WHERE (column1, column2) IN ('A', 12345)
OR (column1, column2) IN ('B', 98765)
Depending on your data, this might be workable:
SELECT *
FROM TABLE T
JOIN (
SELECT 'A' COL1, 12345 COL2
UNION ALL
SELECT 'B', 98765
UNION ALL
SELECT 'C', 44365) AS Matches
ON T.column1 = Matches.COL1
AND T.column2 = Matches.COL2
This turned out to be easy and should have known this.
SELECT *
FROM TABLE
WHERE CONCAT(column1, column2) IN ('A12345','B98765')

how to custom sort data in sql server

I am using Sql server 2008 r2, I need to order by the following data:
CardNo
R-1
R-2
R-12
R-1A
R-3
R-2B
Result should look like this
CardNo
R-1
R-1A
R-2
R-2B
R-3
R-12
I have tried different combinations in order by clause but of no use like:
select * from [Coll2012-13] where
SUBSTRING(CardNo, 1, 1) IN ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'W', 'X', 'Y', 'Z')
AND SUBSTRING(CardNo, 2, 1) IN ('-')
AND SUBSTRING(CardNo, 3, 1) IN ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')
and Landmark='Anandbagh' order by LEN(CardNo),CardNo ASC
Assumption: Values are always of the format 'Letter-Alphanumeric string'
Try this:
select card_no
from [Coll2012-13]
order by left(card_no,1),
case
when isnumeric(substring(card_no,3, len(card_no))) = 1
then cast(substring(card_no,3, len(card_no)) as int)
else cast(substring(card_no,3, patindex('%[A-Z]%',substring(card_no,3, len(card_no)))-1) as int)
end,
case
when patindex('%[A-Z]%', substring(card_no,3,len(card_no))) > 0
then substring(card_no,patindex('%[A-Z]%', substring(card_no,3,len(card_no)))+2,1)
end
How this works: First check the starting letter. Next, check if the alphanumeric part is in fact only numeric. If so, get the integer value of that part. If it is not, get the numeric part of it and use that as the sort value. Finally, if the alphanumeric part does contain a letter, use that as another sort value.
Demo here.
You should replace all non digit chars with "" and convert the rest in a number. Then sort by the number.
You can try to use a function as described here SQL Server 2000: how do I return only the number from a phone number column
for this
A simple - but 'should be maintained' - solution is to create a sorting table and join that table to your result set. The table contains all CardNo values and associates a sort order to them.
EDIT:
CREATE TABLE CardNoOrderHelper (
CardNo VARCHAR(16)
, OrderRank INT CONSTRAINT DF_CardNoOrderHelper_OrderRank DEFAULT 0
, PRIMARY KEY CLUSTERED (
CardNo ASC
)
);
-- Fill your table with the expected sort order (dinstinct insert, than adjust the order ranks)
SELECT
*
FROM
[Coll2012-13] AS T
LEFT JOIN CardNoOrderHelper CH
ON T.CardNo = CH.CardNo
ORDER BY
T.OrderRank
As I said, you have to maintain this table. When your resultset is small this can be done manually.
Try this
with cte
AS
(
select
*
,substring(CardNo, 1, charindex('-')-1) RealRank1
,substring(CardNo, charindex('-')+ 1, 10) RealRank2
from
[Coll2012-13]
)
select
*
from
cte
order by
RealRank1
,RealRank2
I have the similar problem. I have used this query below.
To use this query u must know the ID (string) maximum length and I have adjusted the format in this query to use Mark-Number+Alphabet (example R-1,R-1A, R-11, R-11A, R-1AA,R-1B)
Query:
select
b.CardNo, b.separatorIndex
,b.Mark, b.Mark_length
,case b.isNumericMark1 + b.isNumericMark2 + b.isNumericMark3
when 1 then cast (b.Mark1 as int)
when 2 then cast (b.Mark1 + b.Mark2 as int)
when 3 then cast (b.Mark1 + b.Mark2 + b.Mark3 as int)
end as Mark1
from
(
select
a.CardNo
,charindex('-',a.cardNo,0) as separatorIndex
, len(a.cardNo) - charindex('-',a.cardNo,0) as Mark_length
, substring(a.CardNo,0,charindex('-',a.cardNo,0)) as Mark
, substring(a.CardNo,charIndex('-',a.cardNo,0)+1,1) as Mark1
, isnumeric(substring(a.CardNo,charIndex('-',a.cardNo,0)+1,1*1)) as isNumericMark1
, substring(a.CardNo,charIndex('-',a.cardNo,0)+2,1) as Mark2
, isnumeric(substring(a.CardNo,charIndex('-',a.cardNo,0)+2,1)) as isNumericMark2
, substring(a.CardNo,charIndex('-',a.cardNo,0)+3,1) as Mark3
, isnumeric(substring(a.CardNo,charIndex('-',a.cardNo,0)+3,1)) as isNumericMark3
from [Coll2012-13] a
) b
order by Mark,Mark1,Mark_length
Result:
CardNo separatorIndex Mark Mark_length Mark1
-------------------- -------------- -------------------- ----------- -----------
R-1 2 R 1 1
R-1A 2 R 2 1
R-2 2 R 1 2
R-2B 2 R 2 2
R-3 2 R 1 3
R-12 2 R 2 12
Hope this help.

DECODE with NULL values

I want to insert ZEROS or Spaces when the value is NULL
I tried for small column length and it worked:
INSERT INTO ABCTABLE (COLUMN1)
VALUES ('DECODE(MDSE_CD,NULL,''000'',LPAD(TO_NUMBER(MDSE_CD,''3'','' ''))');
But how do I execute the second query that has around 400 column length:
INSERT INTO ABCTABLE (COLUMN1)
VALUES ('DECODE(MDSE_CD,NULL,''see notes below'',LPAD(TO_NUMBER(MDSE_CD,''400'','' ''))');
Note:How do I insert 400 zeros or spaces when the column is NULL
CREATE TABLE my_test( val VARCHAR2(500));
INSERT INTO my_test
SELECT TO_CHAR(NVL(TO_CHAR(val), rpad(NVL(val,'0'), 400, '0')))
FROM
(WITH t(val) AS
(SELECT '1' FROM dual
UNION
SELECT NULL FROM dual
)
SELECT * FROM t
);
SELECT * FROM my_test;
val
--
1
00000
Because of the DECODE I'm assuming Oracle...
To get 400 zeros in Oracle:
LPAD('0', 400, '0')
The third parameter is what to pad with; in this case zeros.
To get 400 spaces in Oracle:
LPAD(' ', 400)
Since the strings are all the same character you could also use RPAD.