FIND_IN_SET() equivalent in SQL Server - sql-server

SELECT * FROM users WHERE uid IN (SELECT doctors FROM MainPage WHERE Valid=1)
users table uid INT
Mainpage table doctors text with value as 1,2,3,4,5
When I am running the above query, it is only resulting 1 row which is for uid = 1, however I wanted all the 5 rows. So in MySQL I used this query:
SELECT *
FROM users
JOIN MainPage ON FIND_IN_SET(uid, doctors)
WHERE Valid = 1;
It worked. I am trying to find an equivalent in SQL Server for FIND_IN_SET to achieve the same result ?

This might work
SELECT *
FROM users u
WHERE EXISTS (
SELECT *
FROM MainPage
WHERE CONCAT(',',doctors,',') LIKE CONCAT('%,',u.uid,',%')
AND Valid = 1
)

Since SQL Server 2016 (13.x) there is STRING_SPLIT()
SELECT *
FROM users
WHERE uid IN
(SELECT value FROM STRING_SPLIT(
(SELECT doctors FROM MainPage WHERE Valid = 1),
','))

Related

Issue with query in DB2

I was using below query in sql server to update the table "TABLE" using the same table "TABLE". In sql server the below query is working fine.But in DB2 its getting failed.Not sure whether I need to make any change in this query to work in DB2.
The error I am getting in DB2 is
ExampleExceptionFormatter: exception message was: DB2 SQL Error:
SQLCODE=-204, SQLSTATE=42704
This is my input Data and there you can see ENO 679 is repeating in both round 3 and round 4.
My expected output is given below. Here I am taking the ID and round value from round 4 and updating rownumber 3 with the ID value from rownumber 4.
My requirement is to find the ENO which is exist in both round 3 and round 4 and update the values accordingly.
UPDATE TGT
SET TGT.ROUND = SRC.ROUND,
TGT.ID = SRC.ID
FROM TABLE TGT INNER JOIN TABLE SRC
ON TGT.ROUND='3' and SRC.ROUND='4' and TGT.ENO = SRC.ENO
Could someone help here please. I tried something like this.But its not working
UPDATE TABLE
SET ID = (SELECT t.ID
FROM TABLE t, TABLE t2
WHERE t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3'
) ,
ROUND= (SELECT t.ROUND
FROM TABLE t, TABLE t2
WHERE t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3')
where ROUND='3'
You may try this. I think the issue is you are not relating your inner subquery with outer main table
UPDATE TABLE TB
SET TB.ID = (SELECT t.ID
FROM TABLE t, TABLE t2
WHERE TB.ENO=t.ENO ---- added this
and t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3'
) ,
TB.ROUND= (SELECT t.ROUND
FROM TABLE t, TABLE t2
WHERE TB.ENO=t.ENO --- added this
and t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3')
where tb.ROUND='3'
Try this:
UPDATE MY_SAMPLE TGT
SET (ID, ROUND) = (SELECT ID, ROUND FROM MY_SAMPLE WHERE ENO = TGT.ENO AND ROUND = 4)
WHERE ROUND = 4 AND EXISTS (SELECT 1 FROM MY_SAMPLE WHERE ENO = TGT.ENO AND ROUND = 4);
The difference with yours is that the correlated subquery has to be a row-subselect, it has to guarantee zero or one row (and will assign nulls in case of returning zero rows). The EXISTS subquery excludes rows for which the correlated subquery will not return rows.

MS SQL If Selected is NULL Run another statement

I have two sql statements,
select * from UserTable where role='HOD'
select * from UserTable where role='Supervisor'
I want the results to be in a way such that if the first statement returns nothing, I want the second statement to run and if first statement returns something, second statement do not need to run. Is there a way to do it, be it in a stored procedure or a SQLQuery?
Executing two queries is more expensive than executing a single one that returns both result sets. It would be cheaper to filter the results on the client.
Even if you return all results in a single query, you can differentiate the two cases. For example, HOD always comes before Supervisor. You could use a ranking function like ROW_NUMBER() to assign a value to each row, depending on whether it matches HOD or Supervisor:
with a as (
select * ,row_number() over (partition by Role order by Role) as rn
from UserTable
where Role in ('HOD','Supervisor')
)
select *
from a
where rn=1
Another option is to combine a query that returns HOD with a query that returns Supervisor if HOD doesn't exist:
select *
from UserTable
where Role ='HOD'
UNION ALL
select *
from UserTable
where Role ='Supervisor'
AND NOT EXISTS (SELECT 1
from UserTable
where Role ='Supervisor')
The performance of both queries can be improved if Role is part of an index. The first query becomes equivalent to a simple index seek if the table has an index that covers all the returned fields. If the query returns only eg, ID, UserName, Role :
with a as (
select * ,row_number() over (partition by Role order by Role) as rn
from UserTable
where Role in ('HOD','Supervisor')
)
select ID,UserName, Role
from a
where rn=1
and the table has a covering index:
CREATE INDEX IX_UserTable_Roles ON UserTable (Role,ID,UserName)
The resulting execution plan is a single INDEX SEEK on the index
Try This
IF EXISTS (
SELECT 1 FROM UserTable WHERE ROLE = 'HOD'
)
BEGIN
SELECT * FROM UserTable WHERE ROLE = 'HOD'
END
ELSE BEGIN
SELECT * FROM UserTable WHERE ROLE = 'Supervisor'
END
This should do :
IF EXISTS(SELECT 1 FRom UserTable where role='HOD')
Begin
select * from UserTable where role='HOD'
END
ELSE BEGIN
select * from UserTable where role='Supervisor'
END
If you are using Transact SQL then a good page to read about this is https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql
In the Transact SQL instance, the general version of what you are looking for is;
IF Boolean_expression
{ sql_statement | statement_block }
[ ELSE
{ sql_statement | statement_block } ]

Join array of numbers with table in function

I need some support with array type, because it is a new thing for me, so
I have a function:
create or replace type num_array as table of number;
create or replace function functionname(arr_in num_array)
return num_array is
tab num_array;
begin
select id_acc bulk collect into tab from (
SELECT a.id_acc
FROM (SELECT id_acc, parent_acc FROM account) a
connect by nocycle prior a.id_acc=a.parent_acc
start with id_acc in
(
select distinct ID_ACC
from (SELECT id_acc, parent_acc FROM account
) a
where parent_acc = id_acc
connect by nocycle prior a.parent_acc = a.id_acc or parent_acc is null
start with id_acc in (select parent_acc from table_name t,account a where t.id=a.id_acc)));
return tab;
end;
As an input I want to have an array of numbers (id). I want to connect that number (from input) with account table. It is in line:
start with id_acc in (select parent_acc from table_name t,account a where t.id=a.id_acc)));
I would like to join somehow table account with numbers from input,
I was trying to use table(tab()),account a but I got an error.
As output I would like to have result of select query so (return tab).
I'm not sure I understood what you want to achieve. Just to help you with the syntax, look at this:
start with id_acc in (select * from table(arr_in));
Below i have provided a small snippet which basically illustrates your issue with joining Nested Table type with Table.
CREATE OR REPLACE FUNCTION test_ntt_join
RETURN NUMBER_NTT
AS
lv_tab_num NUMBER_NTT;
lv_tab2 NUMBER_NTT;
BEGIN
SELECT LEVEL BULK COLLECT INTO lv_tab_num FROM DUAL CONNECT BY LEVEL < 10;
SELECT COLUMN_VALUE
BULK COLLECT INTO
lv_tab2
FROM TABLE(lv_tab_num) t,
EMP
WHERE emp.empno= t.column_value;
RETURN lv_tab2;
END;
------------------------------------------OUTPUT------------------------------------
select * from table(test_ntt_join);
COLUMN_VALUE
1
1
3
------------------------------------------OUTPUT------------------------------------

What is wrong with this SQL Query in SQL Server Management Studio?

Trying to run this SQL Query and although it says it was executed successfully, it does not return 1 result. Instead, it returns all rows from the database table as it normally does:
SELECT * FROM [Philadelphia].[dbo].[mmgusers_tbl] [WHERE UserName = 'testing' LIMIT 1];
How do I change this to give me only 1 row when executed?
LIMIT 1 is used in mySQL to limit records. In SQL Server, try using the following query:
SELECT TOP 1 * FROM [Philadelphia].[dbo].[mmgusers_tbl] WHERE UserName = 'testing';
Here is what your looking for
SELECT TOP 1 * FROM [Philadelphia].[dbo].[mmgusers_tbl] WHERE UserName = 'testing';
SELECT * FROM [Philadelphia].[dbo].[mmgusers_tbl] WHERE UserName = 'testing'
and only 1 rows matched a UserName of 'testing'
if you just want a single row
SELECT TOP 1 * FROM [Philadelphia].[dbo].[mmgusers_tbl] WHERE UserName = 'testing'
Try this
SELECT Top 1 * FROM [Philadelphia].[dbo].[mmgusers_tbl]
WHERE UserName = 'testing'
(Or)
Select * FROM
(
SELECT *,Row_Number() Over (Order By (Select Null)) AS RN FROM [Philadelphia].[dbo].[mmgusers_tbl] WHERE UserName = 'testing'
) AS T
Where RN = 1

SQL Server Select Where value LIKE(temporary table value)

I have a function in SQL server 2008 that takes a string: 'A,B,C,D' and splits it and creates a table of the values.
Values
------
A
B
C
D
I now want to search a table (Users) Where a column value is LIKE one of the rows (surname) in the above table.
This is what I would like to do:
SELECT * FROM Users WHERE vLastName LIKE 'A%'
SELECT * FROM Users WHERE vLastName LIKE 'B%'
SELECT * FROM Users WHERE vLastName LIKE 'C%'
SELECT * FROM Users WHERE vLastName LIKE 'D%'
If the above is not possible, how else would you do it? Some kind of loop?
I'm using SQL Server 2008
SELECT * FROM Users,NewTable WHERE vLastName LIKE Values + '%'
SELECT * from Users u
JOIN StringSplitterResult r on r.Values = SUBSTRING( u.vLastName, 1,1)

Resources