sql with <> and substring function - sql

The output of query has to return records where company is not equal to 'CABS' OR substring of company until empty space (eg CABS NUTS).The company name can the CABS, COBS, CABST , CABS NUTS , CAB
SELECT *
FROM records
WHERE UPPER(SUBSTR(company, 0, (INSTR(company,' ')-1))) <> 'CABS'
OR COMPANY <> 'CABS'
But the above query is returing CABS NUTS along with COBS , CAB.
I tried using "LIKE CABS" it looks fine but if the company name is "CAB" it will not return "CABS" and CABS NUTS because of like. So LIKE is completely ruled out.
Can anyone please suggest me.

So you want all records where the first 4 characters of the Company field are not "CABS". Okay.
WHERE left(company, 4) != 'CABS'

SELECT
*
FROM
Records
WHERE
LEFT(Company, 4) <> 'CABS'
AND Company <> 'CABS'
Note: Basic TSQL String Comparison is case-insensitive

Can quite work out which ones you do want returns, but have you considered LIKE 'CABS %'

select * from records where company NOT IN (SELECT company
FROM records
WHERE UPPER(SUBSTR(company, 0, (INSTR(company,' ')-1))) = 'CABS'
OR COMPANY = 'CABS')
I think this will fetch the desired records from the records table
RECORDS:
COMPANY
=====================
CAB
CABST
COBS

First, I think you should use AND instead of OR in your compound condition.
Second, you could simplify the condition this way:
WHERE UPPER(SUBSTR(company, 0, (INSTR(company || ' ',' ') - 1))) <> 'CABS'
That is, the company <> 'CABS' part is not needed in this case.

The problem you are getting comes about because the result of the SUBSTR is null if there is not a space. And thanks to three value logic, the result of some_var <> NULL is NULL, rather than TRUE as you might expect.
And example of this is shown by the query below:
with mytab as (
select 1 as myval from dual union all
select 2 as myval from dual union all
select null as myval from dual
)
select *
from mytab
where myval = 1
union all
select *
from mytab
where myval <> 1
This example will only return two rows rather than three rows that you might expect.
There are several ways to rewrite the condition to make it ignore the null result from the substr function. These are listed below. However, as mentioned by one of the other respondents, the two conditions need to be joined using the AND operator rather than OR.
Firstly, you could explicitly check that the column has a space in it using the set of conditions below:
(INSTR(company,' ') = 0 or
UPPER(SUBSTR(company, 0, (INSTR(company,' ')-1))) <> 'CABS') and
COMPANY <> 'CABS'
Another option would be to use the LNNVL function. This is a function that I only recently found out about. It return TRUE from a condition when the result of the condition provided as the input is FALSE or NULL.
lnnvl(UPPER(SUBSTR(company, 0, (INSTR(company,' ')-1))) = 'CABS') and
COMPANY <> 'CABS'
And another option (which would probably be my preferred option) is to use the REGEXP_LIKE function. This is simple, to the point and easy to read.
WHERE not regexp_like(company, '^CABS( |$)')

Related

Remove only first character from the field if it is 0

How to write sql query which will show values skipping first character if it is 0 (only the first character). All values are 3 characters long.
Examples:
numbers
123
023
003
102
should display as follows (after executing the query)
numbers
123
23
03
102
I used the following solution, but it removes all 0's, not just the first. How to fix it so that it only removes the first character if it is 0.
SUBSTRING(numbers, PATINDEX('%[^0]%', numbers+'.'), LEN(numbers))
I will be grateful for your help.
You can use CASE expression:
SELECT CASE WHEN LEFT(numbers, 1) = '0' THEN RIGHT(numbers, 2) ELSE numbers END AS FormattedNumbers
why not using simple substr() ?
select case when substr(mycol,1,1)='0' then substr(mycol,2) else mycol end
from my table
you did not mention your DB so i assumed its oracle. This will work in any RDBMS.
You can use charindex and substring methods to do string manipulation :)
select
case when charindex('0', number) = 1
then substring(number, 2, len(number))
else number end
from (
select '123' number
union all
select '023'
union all
select '003'
union all
select '102'
) a

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)

Check if the first or second condition exists

I have a little problem selecting queries, namely when I want to check the first condition with the code below
select * from VL_Faktura_Queue where FAK_KundenNr=127849 AND (FAK_BoMatNr LIKE '%verk%' AND FAK_VerrechnetBis ='0001-01-01')
, it shows me one position, but when I add a condition where I want to check if there is a FAK_KundenNr with FAK_BomatNr LIKE '% Verk%' OR FAK_BoMatNr Like 'Zus%' also throws me different values that do not fall under FAK_KundenNr = 127849, as I can easily check that it returns my values for this KundenNr, where there is 1 OR 2 condition.
this is my query:
select * from VL_Faktura_Queue where FAK_KundenNr=127849
AND (FAK_BoMatNr LIKE '%verk%' AND FAK_VerrechnetBis ='0001-01-01') --this would be the first condition
or FAK_BoMatNr like 'Zus%' --and this the second condition
This is the individual selection I should get but in one query at the end
so my question is how can i get in one query select from these two query from the picture, thanks everyone for the help
Your parentheses are not sufficient. AND has precedence over OR, so you have FAK_KundenNr = 127849 AND (<first condition)> OR FAK_BoMatNr like 'Zus%'.
SELECT *
FROM VL_Faktura_Queue
WHERE FAK_KundenNr = 127849
AND
(
(FAK_BoMatNr LIKE '%verk%' AND FAK_VerrechnetBis = '0001-01-01')
or
FAK_BoMatNr LIKE 'Zus%'
);
In your requirement, you need to combine the "AND" operator with other logical "OR" operator.
SELECT *
FROM VL_Faktura_Queue
WHERE
(
( FAK_BoMatNr LIKE '%verk%'
AND FAK_VerrechnetBis = '0001-01-01'
) -- 1st Condition
or
(FAK_BoMatNr LIKE 'Zus%') -- 2nd Condition
)
AND FAK_KundenNr = 127849;
Please check if this solution is working for you.

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))