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)
Related
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 } ]
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),
','))
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------------------------------------
I have a table with 12 columns.
I need a query for computing COUNT(*) and selecting all the columns.
I mean I want to have these two queries just in one query:
select *
from mytable
where OneOfTheColumns = something;
select COUNT(*)
from mytable
where OneOfTheColumns = something;
Conditions and tables are the same.
Can I do this?
Thanks a million.
You can use a window function for that
select *,
count(*) over () as total_count
from mytable
where OneOfTheFields = something;
I have a table called telephone_contacts that contain two columns:
telephone_contacts (
Name varchar(100)
Numbers number(20)
)
the column name contains about 20,000 rows.
I want to filter the name by alphabetic , example:
I want a query that get me only the first 6 alphabetic (A , B, C , D ,E ,F G)
Then, a query that get me the last 6 alphabetic (U,V,W,X,Y,Z)
example: the column name contains the following data:
Abe, car, night, range, chicken, zoo, whatsapp,facebook, viber Adu , aramt, Bike, Male, dog,egg
I want a query that get me only (A , B, C , D ,E ,F G) so the results will be
abe ,care ,chicken facebook,adu,aramt,bike, dog, egg
the rest are ignored
In oracle I can do it like this, how do I do it for sybase?
SELECT * FROM user_tab_cols WHERE SUBSTR(UPPER(table_name),1) BETWEEN 'A' and 'Q'
SELECT * FROM user_tab_cols WHERE SUBSTR(UPPER(table_name),1) BETWEEN 'P' and 'Z'
In Sybase you can use the regex (regular expression) to sepecify character ranges [A-G] Assuming your server is set to case insensitive you can do the following:
SELECT * FROM telephone_contacts WHERE name LIKE "[A-G]%"
SELECT * FROM telephone_contacts WHERE name LIKE "[U-Z]%"
or
SELECT * FROM telephone_contacts WHERE name BETWEEN "A%" and "G%"
SELECT * FROM telephone_contacts WHERE name BETWEEN "U%" and "Z%"
If you find that your server is case sensitive, then you can do what was suggested in another answer, and use upper(name)
It's even simpler:
select * from yourtable where upper(name) like "[A-Q]%"
select * from yourtable where upper(name) like "[P-Z]%"