Query condition where a value is in a comma separated string - sql

I have a table in which one of the table columns third_row stores a comma-separated list of numbers as a string but when its value is A then it means a combination of all the possible numbers. How do I approach this so that the query returns all the rows that have the third_row as A and the rest where third_row is equal to one of the values in the comma-separated string?
For reference, here is the format of the table:
first_row
second_row
third_row
0028001070200
50
A
0049048000701
51
01,04,02,31,
I have also tried this query but no luck:
SELECT
sds.scheme_code,
rs.scheme_name
FROM
trea.salary_deduction_schemes sds
LEFT JOIN
trea.receipt_schemes rs
ON sds.scheme_code = rs.scheme_code
WHERE sds.list_object_head = 'A'
OR 16 IN(regexp_split_to_table(sds.list_object_head, E','))

Your method almost works:
WHERE sds.list_object_head = 'A' OR
16 IN (SELECT val::int
FROM regexp_split_to_table(sds.list_object_head, E',') val
)
You can also use string matching:
WHERE ',' || sds.list_object_head || ',' LIKE '%,' || 16 || ',%'
Or you could convert to an array and use array operations.
I would strongly suggest that find a representation other than strings for storing integer values -- preferably another table or perhaps an array.

You can convert the list to an array and use the = any operator:
WHERE sds.list_object_head = 'A'
OR 16 = any(string_to_array(trim(',' from sds.list_object_head), ',')::int[])
The trim() is necessary to get rid of the trailing , that would result in an empty string after applying string_to_array() and that in turn would result in a casting error as an empty string isn't a valid integer.
This is probably a bit faster than using a regex and unnesting the array.

Related

How to fetch only a part of string

I have a column which has inconsistent data. The column named ID and it can have values such as
0897546321
ABC,0876455321
ABC,XYZ,0873647773
ABC,
99756
test only
The SQL query should fetch only Ids which are of 10 digit in length, should begin with a 08 , should be not null and should not contain all characters. And for those values, which have both digits and characters such as ABC,XYZ,0873647773, it should only fetch the 0873647773 . In these kind of values, nothing is fixed, in place of ABC, XYZ , it can be anything and can be of any length.
The column Id is of varchar type.
My try: I tried the following query
select id
from table
where id is not null
and id not like '%[^0-9]%'
and id like '[08]%[0-9]'
and len(id)=10
I am still not sure how should I deal with values like ABC,XYZ,0873647773
P.S - I have no control over the database. I can't change its values.
SQL Server generally has poor support regular expressions, but in this case a judicious use of PATINDEX is viable:
SELECT SUBSTRING(id, PATINDEX('%,08[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],%', ',' + id + ','), 10) AS number
FROM yourTable
WHERE ',' + id + ',' LIKE '%,08[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],%';
Demo
If you normalise your data, and split the delimited data into parts, you can achieve this some what more easily:
SELECT SS.value
FROM dbo.YourTable YT
CROSS APPLY STRING_SPLIT(YT.YourColumn,',') SS
WHERE LEN(SS.value) = 10
AND SS.value NOT LIKE '%[^0-9]%';
If you're on an older version of SQL Server, you'll have to use an alternative String Splitter method (such as a XML splitter or user defined inline table-value function); there are plenty of examples on these already on Stack Overflow.
db<>fiddle

Sybase LIST function truncating results after 256 characters

I'm trying to aggregate a column of strings into one cell by concatenating them together and separating them with commas using syabase's LIST fuction. But the results get truncated after 256 characters. Does anyone know of a way to fix this or if there are any alternatives that would give me what I'm looking for.
For example, if I have a table myTable that looks like this:
myVal
-------------
'0000000001'
'0000000002'
'0000000003'
'0000000004'
'0000000005'
'0000000006'
'0000000007'
'0000000008'
'0000000009'
'0000000010'
'0000000011'
'0000000012'
'0000000013'
'0000000014'
'0000000015'
'0000000016'
'0000000017'
'0000000018'
'0000000019'
'0000000020'
'0000000021'
'0000000022'
'0000000023'
'0000000024'
'0000000025'
'0000000026'
'0000000027'
'0000000028'
'0000000029'
'0000000030'
then run the following query:
select list(myVal,',') as myResult from myTable
I get the following result
myResult
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0000000001,0000000002,0000000003,0000000004,0000000005,0000000006,0000000007,0000000008,0000000009,0000000010,0000000011,0000000012,0000000013,0000000014,0000000015,0000000016,0000000017,0000000018,0000000019,0000000020,0000000021,0000000022,0000000023,000
Notice the result string gets truncated after 0000000023
Try this:
SELECT
LIST( CAST( myVal AS nvarchar(max) ), ',' )
FROM
myTable

How to multi-split a string (WHERE IN query)

I am passing a string as param (via massivejs) into my query. The string is formatted as: param = 'red, blue, green'. The param itself does not have a fixed length (',' being the delimiter) as it is populated through what the user sends in (but is maxed out at 10 elements).
How would I break the string down into individual strings inside my query?
Eg of what I am trying to do:
SELECT * FROM table
WHERE name IN (param);
I know this works but is very very crude:
SELECT * FROM table
WHERE name IN (split_part(param, ',', 1), split_part(param, ',', 2) .......)) -- keep going.
Essentially I want to have ('red', 'blue', 'green' ....) inside the IN parenthesis. Is there a nicer way of accomplishing this?
You could use the string_to_array function to split the string to an array and then use the any function to check if your element is contained in it:
SELECT *
FROM mytable
WHERE name = ANY(STRING_TO_ARRAY(param, ','));

group by with empty string

I need to make 2 selects and put them together with an UNION. So far, so good. The problem is, for fields with no value, I can put just "0" instead of an actual column, but what do I put for string values? I know that the following example doesn't work:
Select field1, field2, 0, 0 from AnyTable
...
UNION
Select '','',sum(field3),sum(field4) from AnyTable2
...
So, what do I use instead of ' '?
An zero length string in Oracle is considered as NULL. You need to use NVL function to convert the NULL values into some value.
SQL> select nvl(null, 'This is null') val from dual;
VAL
------------
This is null
Note : Take care of the individual DATA TYPE of each column in the UNION

sql, using a subquery in the like operator

why does this work,
select*
from some_table
WHERE some_column_name like '%i%'
and not this?
select*
from some_table
WHERE
some_column_name like (select ''''+'%' +value +'%' + '''' as val
from [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ')
where idx = 0)
I am trying to search for individual words instead of the whole phrase, the split function above will split the string on space characters and plug the results into a table with two columns, idx and value.
the LIKE operator takes a string for an argument. It cannot be used on a table, which I assume your function returns.
I think what you want to do is JOIN to the function, and then check where LIKE fn.Value:
select *
from some_table t
INNER JOIN (select value as val
from [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ')
where idx = 0) f
ON t.some_column_name like '%'+f.val+'%'
If your subquery is guaranteed to only return one result, you could try putting the modulo symbols around it instead of inside it:
LIKE '%' + (YourSubQuery) + '%'
One possible reason is because you are appending single quotes onto the beginning and end of the string, and none of the values actually store single quotes in the string.
Another reason is might not work is because the subquery returns more than one row or zero rows. The function fn_split() is your own function, so I don't know what it returns. You have a subquery in a context where it can return at most one row and one column. That is called a scalar subquery. If the subquery returns more than one row, you will get an error. If the subquery returns no rows -- for instance, if idx starts counting at 1 rather than 0 -- then it will return NULL which fails the test.
If you want to find a match this way, I would recommend exists:
select t.*
from some_table t
where exists (select 1 as val
from [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ') s
where s.idx = 0 and
t.some_column_name like '%' + value + '%'
);
The results of your sub-query is a literal string. The % symbol isn't seen as a wildcard. Also, does your functions return multiple rows? If so, LIKE operator can only evaluate a single value.
If your functions does return a single value, I would suggest looking into using Dynamic SQL. Something like the following:
DECLARE #SQL VARCHAR(MAX), #WildCard VARCHAR(MAX)
SELECT #WildCard = '%' + value + '%'
FROM [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ')
WHERE idx = 0
SET #SQL = 'SELECT * FROM some_table WHERE some_column_name like ''' + #WildCardWildCard + ''''
EXEC(#SQL)