Can somebody verify this for me in sql or teradata - sql

I have a line of code in Oracle and I had to convert it into Teradata.
The Oracle query is
/* add to avoid invalid number due to junk in column */
AND regexp_instr(table.column, ''[^[:digit:]]'', 1, 1) = 0
The code I have written in Teradata
AND (CASE WHEN (POSITION('' '' IN TRIM(table.column)) > 0) OR (UPPER(TRIM(table.column))
(CASESPECIFIC) <> LOWER(TRIM(table.column)) (CASESPECIFIC))
THEN 1 ELSE 0 end ) = 0
The column is defined as a VARCHAR(20) but I only want to select rows where the data is all numeric. I cannot verify the Teradata query as it is a very long-running query and I don't have access to create tables or rather I can not verify the out put on the database I have. I some how tried and it looks like it works but I once wanted to verify the syntax and my understanding of REGEXP_INSTR.

If I am reading correctly and based on my testing this will break your logic (both return 1):
SELECT (CASE WHEN (POSITION('' '' IN TRIM('1234')) > 0) OR (UPPER(TRIM('1234'))
(CASESPECIFIC) <> LOWER(TRIM('1234')) (CASESPECIFIC))
THEN 1 ELSE 0 END )
SELECT (CASE WHEN (POSITION('' '' IN TRIM('abcd ef1')) > 0) OR (UPPER(TRIM('abcd ef1'))
(CASESPECIFIC) <> LOWER(TRIM('abcd ef1')) (CASESPECIFIC))
THEN 1 ELSE 0 END )
The Teradata Developer's Exchange contains a library of Oracle functions that have been converted to Teradata UDF's that may help you address this problem. With a little effort you could write your own UDF around the isdigit() C function. (isdigit)
It may not be helpful now, but one of the recently announced Teradata 14.0 features is support of regular expressions.
EDIT: Added TD 14 example with REGEXP_INSTR that should solve the problem
SELECT table.column
FROM table
WHERE REGEXP_INSTR(table.column, '[^[digit]])') = 0;

Related

How to ignore specific string value when using pattern and patindex function in SQL Server Query?

I have this query here.
WITH Cte_Reverse
AS (
SELECT CASE PATINDEX('%[^0-9.- ]%', REVERSE(EmailName))
WHEN 0
THEN REVERSE(EmailName)
ELSE left(REVERSE(EmailName), PATINDEX('%[^0-9.- ]%', REVERSE(EmailName)) - 1)
END AS Platform_Campaign_ID,
EmailName
FROM [Arrakis].[xtemp].[Stage_SendJobs_Marketing]
)
SELECT REVERSE(Platform_Campaign_ID) AS Platform_Campaign_ID, EmailName
FROM Cte_Reverse
WHERE REVERSE(Platform_Campaign_ID) <> '2020'
AND REVERSE(Platform_Campaign_ID) <> ''
AND LEN(REVERSE(Platform_Campaign_ID)) = 4;
It is working for the most part, below is a screenshot of the result set.
The query I posted above extracts the 4 numbers to the right out of the initial value that is set for the column I am extracting out of. But I am unable to figure out how I can also have the query ignore cases when the right most value is -v2, -v1, etc. essentially anything with -v and whatever number version it is.
If you want four digits, then one method is:
select substring(emailname, patindex('%[0-9][0-9][0-9][0-9]%', emailname), 4)

SQL CONCAT drops zeros from expression

I am trying different ways to put a 0 in front of month less than 10.
I tried the following expression but the 0 get dropped.
What am I doing wrong?
CASE
WHEN month([Transact_Date]) < 10
THEN CONCAT(str(0),STR(month([Transact_Date]),1))
ELSE month([Transact_Date])
END AS month_w_0
Thanks!
Tom
I think a left padding trick is what you want here. Assuming your database be SQL Server:
SELECT RIGHT('00' + STR(MONTH([Transact_Date])), 2) AS month_w_0
FROM yourTable;
You don't need a CASE expression for this. In more recent versions of SQL Server, the FORMAT function might also be able to handle this.
I have tested this and it returns the result you want:
select CASE WHEN mnt < 10 THEN
concat('0' , mnt)
ELSE mnt
END AS month_w_0
from ( select month([Transact_Date]) mnt
from test_t) A
I have realised what your problem is. YOu can do it this way too:
SELECT
CASE
WHEN month([Transact_Date]) < 10
THEN CONCAT(str(0),STR(month([Transact_Date]),1))
ELSE STR(month([Transact_Date]),1)
END AS month_w_0
from test_t
The problem is only the else part and I believe that is because case when clause returns only one type od data. In your then part you have tryed to retunr string and in the else part number.
Hope this helps...
Here is a demo

Invalid argument for function integer IBM DB2

I need to filter out rows in table where numer_lini column has number in it and it is between 100 and 999, below code works just fine when i comment out line where i cast marsnr to integer. However when i try to use it i get error: Invalid character found in a character string argument of the function "INTEGER". when looking at the list seems like replace and translate filters only numbers just fine and select only contains legit numbers (list of unique values is not long so its easy to scan by eye). So why does it fail to cast something? I also tried using integer(marsnr), but it produces the same error. I need casting because i need numeric range, otherwise i get results like 7,80 and so on. As I mentioned Im using IBM DB2 database.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where numer_lini in (
select marsnr
from (
select
distinct numer_lini marsnr
from alaska.trasa
where case
when replace(translate(numer_lini, '0','123456789','0'),'0','') = ''
then numer_lini
else 'no'
end <> 'no'
)
where cast(marsnr as integer) between 100 and 999
)
fetch first 300 rows only
If you look at the optimized SQL from the Db2 explain, you will see that Db2 has collapsed your code into a single select.
SELECT DISTINCT Q2.NUMER_LINI AS "NUMER_LINI",
Q2.WAR_TRASY AS "WAR_TRASY",
Q2.ID_PRZ1 AS "ID_PRZ1",
Q2.ID_PRZ2 AS "ID_PRZ2",
Q1.NUMER_LINI
FROM ALASKA.TRASA AS Q1,
ALASKA.TRASA AS Q2
WHERE (Q2.NUMER_LINI = Q1.NUMER_LINI)
AND (100 <= INTEGER(Q1.NUMER_LINI))
AND (INTEGER(Q1.NUMER_LINI) <= 999)
AND (CASE WHEN (REPLACE(TRANSLATE(Q1.NUMER_LINI,
'0',
'123456789',
'0'),
'0',
'') = '') THEN Q1.NUMER_LINI
ELSE 'no' END <> 'no')
Use a CASE to force Db2 to do the "is integer" check first. Also, you don't check for the empty string.
E.g. with this table and data
‪create‬‎ ‪TABLE‬‎ ‪alaska‬‎.‪trasa‬‎ ‪‬‎(‪numer_lini‬‎ ‪VARCHAR‬‎(‪10‬‎)‪‬‎,‪‬‎ ‪war_trasy‬‎ ‪INT‬‎ ‪‬‎,‪‬‎ ‪id_prz1‬‎ ‪INT‬‎,‪‬‎ ‪id_prz2‬‎ ‪INT‬‎)‪;
insert into alaska.trasa values ('',1,1,1),('99',1,1,1),('500',1,1,1),('3000',1,1,1),('00300',1,1,1),('AXS',1,1,1);
This SQL works
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when translate(numer_lini, '','0123456789') = ''
and numer_lini <> ''
then integer(numer_lini) else 0 end
between 100 and 999
Although that does fail if there is an embedded space in the input. E.g. '30 0'. To cater for that, a regular expressing is probably preferred. E.g.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when regexp_like(numer_lini, '^\s*[+-]?\s*((\d+\.?\d*)|(\d*\.?\d+))\s*$'))
then integer(numer_lini) else 0 end
between 100 and 999

SQL query: convert

I'm trying to read a column from a database using a SQL query. The column consists of empty string or numbers as strings, such as
"7500" "4460" "" "2900" "2640" "1850" "" "2570" "9050" "8000" "9600"
I'm trying to find the right sql query to extract all the numbers (as integers) and removing the empty ones, but I'm stuck. So far I've got
SELECT *
FROM base
WHERE CONVERT(INT, code) IS NOT NULL
Done in program R (package sqldf)
If all columns are valid integers, you could use:
select * , cast(code as int) IntCode
from base
where code <> ''
To prevent cases when field code is not a valid number, use:
select *, cast(codeN as int) IntCode
from base
cross apply (select case when code <> '' and not code like '%[^0-9]%' then code else NULL end) N(codeN)
where codeN is not null
SQL Fiddle
UPDATE
To find rows where code is not a valid number, use
select * from base where code like '%[^0-9]%'
select *
from base
where col like '[1-9]%'
Example: http://sqlfiddle.com/#!6/f7626/2/0
If you don't need to test for the number being valid, ie. a string such as '909XY2' then this may run marginally faster, more or less depending on the size of the table
Is this what you want?
SELECT (case when code not like '%[^0-9]%' then cast(code as int) end)
FROM base
WHERE code <> '' and code not like '%[^0-9]%';
The conditions are repeated in the where and case on purpose. SQL Server does not guarantee that where filters are applied before logic in the select, so you can get an error with conversions. More recent versions of SQL Server have try_convert() to fix this problem.
Using sqldf with the default sqlite database and this test data:
DF <- data.frame(a = c("7500", "4460", "", "2900", "2640", "1850", "", "2570",
"9050", "8000", "9600"), stringsAsFactors = FALSE)
try this:
library(sqldf)
sqldf("select cast(a as aint) as aint from DF where length(a) > 0")
giving:
aint
1 7500
2 4460
3 2900
4 2640
5 1850
6 2570
7 9050
8 8000
9 9600
Note In plain R one could write:
transform(subset(DF, nchar(a) > 0), a = as.integer(a))

SQL Server: interpreting 'y' as BIT value

In C, when you compared true/false value to 1/0, it worked very well.
I would want the similar possibility with SQL Server - when I have a bit column, I would like to compare myBitField = 'y' / myBitField = 'n'
Is there anything I can do about that? Maybe change some SQL interpreter settings or something?
Example of what I would like to do:
select * from
(
select CAST(1 AS BIT) as result
) as main
where main.result = 'y'
Currently, it throws an error, and I would like it to return 1/true/'y', whatever, but I would like it to be able to make that comparison.
I suppose you want to do it for some yes/no thing. But this is generally a wrong concept, your application which is accessing the SQL Server should interpret y as a 1 and n as a 0 and afterwards set the correct parameters for the query. You should not (actually I'm temped to write "must not") do this in SQL Server, that's what you have a business logic for.
As others have said, BIT and CHAR / VARCHAR are entirely different datatypes. But if you want to cast them during the select, you can use CASE expression like so:
-- Reading string as BIT
SELECT CAST(CASE RESULT WHEN 'Y' THEN 1 WHEN 'N' THEN 0 ELSE NULL END AS BIT) RESULT
-- Reading BIT as string
SELECT CAST(CASE RESULT WHEN 1 THEN 'Y' WHEN 0 THEN 'N' ELSE NULL END AS CHAR(1)) RESULT
And that's about as far as your options go here, far as I can understand. :)