T-SQL Comma delimited value from resultset to in clause in Subquery - sql

I have an issue where in my data I will have a record returned where a column value will look like
-- query
Select col1 from myTable where id = 23
-- result of col1
111, 104, 34, 45
I want to feed these values to an in clause. So far I have tried:
-- Query 2 -- try 1
Select * from mytableTwo
where myfield in (
SELECT col1
from myTable where id = 23)
-- Query 2 -- try 2
Select * from mytableTwo
where myfield in (
SELECT '''' +
Replace(col1, ',', ''',''') + ''''
from myTable where id = 23)
-- query 2 test -- This works and will return data, so I verify here that data exists
Select * from mytableTwo
where myfield in ('111', '104', '34', '45')
Why aren't query 2 try 1 or 2 working?

You don't want an in clause. You want to use like:
select *
from myTableTwo t2
where exists (select 1
from myTable t
where id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %'
);
This uses like for the comparison in the list. It uses a subquery for the value. You could also phrase this as a join by doing:
select t2.*
from myTableTwo t2 join
myTable t
on t.id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %';
However, this could multiply the number of rows in the output if there is more than one row with id = 23 in myTable.

If you observe closely, Query 2 -- try 1 & Query 2 -- try 2 are considered as single value.
like this :
WHERE myfield in ('111, 104, 34, 45')
which is not same as :
WHERE myfield in ('111', '104', '34', '45')
So, If you intend to filter myTable rows from MyTableTwo, you need to extract the values of fields column data to a table variable/table valued function and filter the data.
I have created a table valued function which takes comma seperated string and returns a table value.
you can refer here T-SQL : Comma separated values to table
Final code to filter the data :
DECLARE #filteredIds VARCHAR(100)
-- Get the filter data
SELECT #filteredIds = col1
FROM myTable WHERE id = 23
-- TODO : Get the script for [dbo].[GetDelimitedStringToTable]
-- from the given link and execute before this
SELECT *
FROM mytableTwo T
CROSS APPLY [dbo].[GetDelimitedStringToTable] ( #filteredIds, ',') F
WHERE T.myfield = F.Value
Please let me know If this helps you!

I suppose col is a character type, whose result would be like like '111, 104, 34, 45'. If this is your situation, it's not the best of the world (denormalized database), but you can still relate these tables by using character operators like LIKE or CHARINDEX. The only gotcha is to convert the numeric column to character -- the default conversion between character and numeric is numeric and it will cause a conversion error.
Since #Gordon, responded using LIKE, I present a solution using CHARINDEX:
SELECT *
FROM mytableTwo tb2
WHERE EXISTS (
SELECT 'x'
FROM myTable tb1
WHERE tb1.id = 23
AND CHARINDEX(CONVERT(VARCHAR(20), tb2.myfield), tb1.col1) > 0
)

Related

Check if a value starts with one of the value of a column

Hi I'd like to check if a value starts with one of the value of a another column.
t1 | t2
----------
3253 | 123
1234 | 000
9876 | 932
So here for example I should have True for the value 1234 because it starts with 123.
I should have false for the other values.
I can't find any solutions.
Thank you in advance for you help !
I already tried :
t1 LIKE (t2 || '%')
starts_with(t1,t2)
starts_with(t1, (select t2))
Using t1 LIKE (t2 || '%') should be able to get you close to what I think you need, however maybe you are just missing a bit of script logic?
Ignoring any platform specific language (I don't use Big Query), this is just to show the logic that might help you get the result you desire
With the data as:
create table my_table
(t1 number,
t2 number);
insert into my_table values(3253,123);
insert into my_table values(1234,000);
insert into my_table values(9876,932);
You can use a case statement wrapped in a sum to count the matches using like t2||'%. Any value in the resulting column that is 1 or greater should be read as True, and value of 0 as False.
SELECT a.t1,
Sum(CASE
WHEN a.t1 LIKE b.t2
|| '%' THEN 1
ELSE 0
END) AS starts_with
FROM my_table a,
my_table b
GROUP BY a.t1
This gives the output
T1 STARTS_WITH
9876 0
1234 1
3253 0
That works for me :
-- To match your example
WITH T (t1,t2) AS
(
SELECT * FROM (VALUES (3253,123),(1234,000),(9876,932))t(t1,t2)
)
-- What your query should like
SELECT TAB1.t1,TAB1.t2, Tab2.t2
FROM T AS Tab1
CROSS JOIN T AS Tab2
WHERE CAST(TAB1.t1 AS STRING) LIKE (CAST(TAB2.t2 AS STRING) + '%')
Another option to try
select * except(check),
regexp_contains(t1, check)
from (
select *, r'^' || string_agg(t2, '|') over() check
from your_table
)
if applied to sample data in your question - output is

To check if string contains specific number or not

I have two columns in two different tables.
First column is number like 0493484402 and second column is audit_detail like 'addr_mastersubscription has changed from 32488141893 to 32488141973'.
Audit detail column may have different type of string other than above. I have to check only in above type mentioned strings
I have to check whether first column value is present or not in second column at position of Second number.
If the number is not present I need that number as output
I am using oracel SQL developer
Second column datatype is clob and there is not comman filed in both table's
First column data type is varchar
Use REGEXP_LIKE:
SELECT *
FROM yourTable
WHERE REGEXP_LIKE (col2, ' to ' || col1 || '$');
You need to check the two conditions then you can use REGEXP_SUBSTR and REGEXP_LIKE as follows:
SELECT * FROM YOUR_TABLE
WHERE REGEXP_LIKE(SECOND_COLUMN, '^addr_mastersubscription has changed from [0-9]+ to [0-9]+$')
AND TO_NUMBER(FIRST_COLUMN) = TO_NUMBER(REGEXP_SUBSTR(SECOND_COLUMN,'[0-9]+$'))
This is how I understood the question.
Sample data (lines #1 - 9) contain additional ID column (unless you're planning to do cross join between those two tables) which is used to join taba and tabb.
regexp_substr looks for the second number in tabb's col column, which is compared to taba.col. I displayed whether it exists there or not; you can display whatever you want.
Query you might need begins at line #11.
SQL> with
2 taba (id, col) as
3 (select 1, '0493484402' from dual union all
4 select 2, '012345' from dual
5 ),
6 tabb (id, col) as
7 (select 1, 'addr_mastersubscription has changed from 32488141893 to 32488141973' from dual union all
8 select 2, 'nothing changed from 098776 to 012345' from dual
9 )
10 --
11 select a.id,
12 case when a.col = regexp_substr(b.col, '\d+', 1, 2) then a.col || ' exists in tabb'
13 else a.col || ' does not exist in tabb'
14 end result
15 from taba a join tabb b on a.id = b.id;
ID RESULT
---------- ---------------------------------
1 0493484402 does not exist in tabb
2 012345 exists in tabb
SQL>
You can use INSTR(), names itself defines in string where we can check if a particular string is available in the respective column.
Please use below query,
select t1.* from table1 t1
inner join table2 t2
on (instr(t1.first_column, t2.second_column) = 0);
instr(t1.first_column, t2.second_column) = 0 This condition provides you unmatching columns
instr(t1.first_column, t2.second_column) > 0 This condition provides you matching strings

SQL - Run Select Statement Based On Where Query

Hi i want to create a query which does the following. When the paramter 25 is selected it only runs part A of the query, if any other number is selected run both Table A and B select queries.
Example Below:
DECLARE #Type varchar (200)
select * from
(SELECT sort_code FROM dbo.Test 1
WHERE FUNDING_YEAR = 26)
union
(SELECT sort_code FROM dbo.Test 2
WHERE FUNDING_YEAR = 26)
Where case when #Type = 25 then select * from table2 else table 1
You just need to reference the variable in the WHERE clause
SELECT *
FROM TableA
WHERE #Type = 25
UNION
SELECT *
FROM TableB
The query above will always select everything in TableB and will only select everything in TableA when the variable is equal to 25.
Since you are using SSRS, what I would do is write the query to return all of the rows and then apply a filter in the SSRS report when the Paramater is 25. I wouldn't pass a paramater value to the SQL side unless it greatly reduces the run time of the query.
(I would have put this in a comment.)

How to find each case of matching pattern within a string and return as rows

I'm trying to identify reference numbers contained in strings in a column. The table looks something like this:
col1 col2
1 fgREF1234fhjdREF1235hgkjREF1236
2 hREF1237hjdfREF1238djhfhs
Need to write an SQL query that identifies the 'REF' followed by the 4 digits and returns each in its own row.
The output should look like this:
col1 ref
1 REF1234
1 REF1235
1 REF1236
2 REF1237
2 REF1238
I have tried:
select
case when substr(substr(col2, instr(col2, 'REF'), 7), 1, 1) like 'R'
then substr(col2, instr(col2, 'R'), 7) else null end ref
from table
...but this will only identify the first match in the string.
I am using Oracle SQL but ideally the solution would be able to be converted to other SQL variants.
Any help would be much appreciated!
You can use regexp_substr delimited by connect by level <= regexp_count(col2,'REF') ( the appearance time of the pattern string REF within the strings col2 )
with t(col1,col2) as
(
select 1,'fgREF1234fhjdREF1235hgkjREF1236' from dual union all
select 2,'hREF1237hjdfREF1238djhfhs' from dual
)
select col1,
regexp_substr(col2,'REF[0-9]+',1,level) as ref
from t
connect by level <= regexp_count(col2,'REF')
and prior col1 = col1
and prior sys_guid() is not null;
Demo
You can use the below code to get the desired result :-
select x.col1, explode(x.ref) as ref from (
select col1,split(trim(regexp_replace(col2,'[^REF0-9]',' ')),' ') as ref
from inp

SQL query to select with Range condition in source table

Have a scenario to select the value from table where range condition is present in source table.
Like,
TableA
ID value condition
1 20 A-M
2 50 N-Z
Select value from TableA where condition = 'C%'
--want to select TableA value from TableB by passing person name starts with like,
-- Here C is item name starts with
-- Should compare with range (A-M) and return first row.
-- Condition column is varchar(3)
I have seen the solution on other way where range can be compared with input value, but here the range is present in the source table. Please help.
If I have understood what you are after correctly you can use
SELECT TOP 1 B.*
FROM TableB B
WHERE B.Name LIKE (SELECT CONCAT('[',condition,']%') FROM TableA WHERE ID =1)
ORDER BY B.Id
If I understand correctly, you should be structuring TableA as:
ID value Lower Upper
1 20 A M
2 50 N Z
Then you want:
select a.*
from tableA a
where left(#name, 1) between a.lower and a.upper;
You can get this to work with your format, by doing:
select a.*
from tableA a
where left(#name, 1) between left(a.condition) and right(a.condition);
But I don't recommend that. Better to store the condition in two columns.
I would use QUOTENAME() function as
SELECT *
FROM TableA
WHERE #Condition LIKE QUOTENAME(Condition);
This will be as
WHERE 'C' LIKE [A-M] --return True
Demo1
Demo2
Always you should try to add data and DDL for setup correctly the test scenario, here my proposed solution:
DECLARE #SourceA AS TABLE
(
ID INT,
Value INT,
Condition VARCHAR(100)
);
INSERT INTO #SourceA ( ID ,
Value ,
Condition
)
VALUES ( 1 , -- ID - int
110 , -- Value - int
'A-M' -- Condition - varchar(100)
),(2,250,'N-Z')
DECLARE #Alphabet VARCHAR(200)='A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
; WITH MyCTE AS
(
SELECT ID,Value,Condition, SUBSTRING(#Alphabet, PATINDEX('%'+ LEFT(Condition,1) + '%' ,#Alphabet),(LEN(#Alphabet)-PATINDEX('%'+ RIGHT(Condition,1) + '%' ,#Alphabet))+1) AS FormattedCondition
FROM #SourceA
)
SELECT * FROM MyCTE
WHERE MyCTE.FormattedCondition LIKE '%C%'