Using inline SELECT with IN operator - sql

I want to select from one table based on who run the SP. For example if executer has Management role the they can see all records but if executer is Employee then they just see records for all employees. There are some roles like Seller, StockKeeper , ... .
Please consider this sudo code, I want to write a code like this but I got error:
Declare #Role varchar(30)
select *
from MyTable
where Status in (IIF(#Role = 'Employee', select -1 , select -1, 0, 1))
OR
select *
from MyTable
where Status in (case #Role when 'Employee' then select -1 else select -1, 0 , 1 end)
Error:
Incorrect syntax near the keyword 'select'.
Incorrect syntax near the keyword 'else'.
Incorrect syntax near ')'.
Is there any way to combine inline SELECT and IN operator?
Thanks
Edit 1)
Sample Data:
Id Value Status
----------------------------
1 10 -1
2 20 0
3 30 -1
4 40 1
5 50 -1
6 60 0
7 70 1
8 80 -1
for Employee I want to get this result:
Id Value Status
----------------------------
1 10 -1
3 30 -1
5 50 -1
8 80 -1
for Manager I want to get All records.

Use UNION to build the full list of allowable statuses in a conditional manner:
SELECT *
FROM MyTable
WHERE [Status] IN (
-- Everyone gets this role
SELECT -1
UNION ALL
-- Only special people get this role
SELECT 0
WHERE #Role <> 'Employee'
-- Only special people get this role
UNION ALL
SELECT 1
WHERE #Role <> 'Employee'
);
Assuming your sample data is reflective of the bigger picture you could simplify that down to:
SELECT *
FROM MyTable
-- Everyone gets this status
WHERE [Status] = -1
-- Only special people get these statuses
OR (#Role <> 'Employee' AND [Status] IN (0, 1);
Notes:
CASE is an expression i.e. returns a scalar value. Its not a switch statement.
Sub-queries require brackets around them, so even if case allowed it you would still need (select -1) rather than select -1.

If I understand correctly, you can try to use conditions to judge your expected result.
if your input #Role is Manager get all data, otherwise Employee will get -1
Declare #Role varchar(30)
SELECT *
FROM MyTable
WHERE (#Role = 'Employee' AND Status = -1)
OR (#Role = 'Manager')
sqlfiddle

Related

Comparison operator in count() is not working

SELECT 15 > 14 FROM Duel;
This code snippet is working in MySql but not in SQL Server:
SQL Error(102): Incorrect syntax near '>'
I have a requirement where I want to see if at least 1 record exist return 1 or else 0
SELECT count(emp.name) > 0
FROM ****
WHERE *** IN (***)
Check the db fiddle https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=348709a562ad02cbe88abf01a37229f1
I think you are looking for having
SELECT 1 from new_table_name
having count(empName)>0
Update
You can use SIGN(). It returns 1 when result is positive and 0 when the result is 0
SELECT SIGN(COUNT(*)) FROM new_table_name
Check fiddle here
Try case statement -
select case when count(emp.name) > 0 then 1 else 0 end
from ****
where *** IN (***)
You can try EXISTS clause
IF EXISTS (SELECT 1 emp.name
FROM ****
WHERE *** IN (***))
BEGIN
SELECT 1
END
ELSE
SELECT 0
END
As you want to return either 1 or 0, you need to define the values in CASE statement.
select case when exists(SELECT emp.name
FROM ****
WHERE *** IN (***)) then 1 else 0 end
Don't use COUNT. You don't want to count the rows, just to see if there is one. And don't use logic like IF, just use CASE.
SELECT CASE WHEN EXISTS (SELECT 1 FROM **** WHERE **** IN (****))
THEN 1
ELSE 0
END;
You may want to use a CTE like this:
WITH T (C)
AS
-- Select the first record with a value in emp.name
(
SELECT TOP 1 1
FROM **** emp
WHERE *** IN (***)
AND emp.name IS NOT NULL
)
-- just count the elements of T
SELECT COUNT(1) FROM T
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=3514827fadaf6b8d19c2658008df0a99
If you prefer the one-line solution without having to COUNT all records, here is an alternative:
SELECT IIF(exists(select TOP 1 1 from **** emp where emp.name IS NOT NULL), 1, 0)
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=be6c753a6ddb164524576061c3b8802e
All answer provided by is working fine. But SQL Server already provides comparison function.
SELECT IIF(count(erm.employee_code) > 0, 1, 0)
FROM ****
WHERE *** IN (***)

Determine if any values satisfy a condition

How do I write an effiecient query to determine if 1 or more values are 10+ in a column. I am aware that I can count the values but this will scan all the records. Here is what I have so far:
SELECT COUNT(*) FROM MyTable WHERE [state] = 12 AND age > 110
I want this query to stop when it find the first person over 110 not scan the entire table. Is this possible?
You can use a subquery to return 1 or no row using this query:
SELECT TOP 1 1 as row_exists
FROM MyTable
WHERE [state] = 12 AND age > 110;
You can use a subquery to return 1 or NULL using this as a subquery:
SELECT (SELECT TOP 1 1 FROM MyTable WHERE [state] = 12 AND age > 110
) as row_exists;
You can put this into T-SQL using:
IF (EXISTS (SELECT 1 FROM MyTable WHERE [state] = 12 AND age > 110))
BEGIN
. . .
END;
TOP is not needed in an EXISTS subquery.
So you wish to have the scalar Boolean result? The exists will quite once any row matches the condition
DECLARE #Result bit =
(SELECT CASE WHEN EXISTS(SELECT * FROM MyTable WHERE [state] = 12 AND age > 110) THEN 1 ELSE 0 END)
I am not sure wether the it is helpful for you, but you can try to test:
For example you can want to determine the result set row count is 100.
you can use top 100 base your statement.
if the orignal result lines is more than 100, then ##ROWCOUNT will be true.
SELECT TOP 100 FROM MyTable WHERE [state] = 12 AND age > 110
IF ##ROWCOUNT=100
PRINT 'True'
ELSE
PRINT 'Flase'

Stuck on a slightly tricky query, trying to ignore multiple results based on a single field

Here is a simple database representation of what I'm stuck on:
IDNumber TimeSpent Completed
1 0 No
1 0 No
1 2 No
2 0 No
3 0 No
I'm currently querying the database as such...
"SELECT Distinct (IDNumber) AS Info FROM TestTable
ORDER BY WorkOrderNumber";
And it gives me back the results
1
2
3
Which is expected.
Now, I'd like to adjust it to where any instance of an IDNumber that have TimeSpent != 0 or Completed != No means that the IDNumber isn't grabbed at all. So for example in the database given, since TimeSpent = 2, I don't want IDNumber 1 to be returned in my query at all.
My first instinct was to jump to something like this...
"SELECT Distinct (IDNumber) AS Info FROM TestTable
WHERE TimeSpent='0' AND Completed='No'
ORDER BY WorkOrderNumber";
But obviously that wouldn't work. It would correctly ignore one of the IDNumber 1's but since two others still satisfy the WHERE clause it would still return 1.
Any pointers here?
SELECT DISTINCT IDNumber
FROM TestTable
WHERE IDNumber NOT IN
(SELECT IDNUmber FROM TestTable WHERE TimeSPent <> 0 OR Completed <> 'No')
You can do this with an aggregation, using a having clause:
select IDNumber
from TestTable
group by IDNumber
having sum(case when TimeSpent = 0 then 1 else 0 end) = 0 and
sum(case when Completed = 'No' then 1 else 0 end) = 0
The having clause is counting the number of rows that meet each condition. The = 0 is simply saying that there are no matches.
I prefer the aggregation method because it is more flexible in terms of the conditions that you can set on the groups.

If null, return multiple values

I had posted a similar question earlier - a slightly different requirement here.
I have a textBox which returns the user-selected 'Number' value.(eg. : 100,200,300)
What needs to be done is basically check a table MyTable if a record/records exist for the particular Number value selected by user. If it returns NULL, then I need to return the records for the default Number value of 999.
MyTable:
id Number MyVal
1 100 55
2 200 66
3 400 22
4 400 12
5 999 23
6 999 24
Here's what I have so far :(Assuming textBoxInput(Number) = 300)
SELECT Myval
from MyTable
where id in (
SELECT ISNULL(
SELECT id
from MyTable
where Number=300,
select id
from MyTable
where Number = 999
)
)
So here, since Number=300 does not exist in the table, return the records for Number=999.
But when I run this query, I'm getting an error 'Subquery returned more than 1 value...'
Any suggestions/ideas?
This should work:
SELECT Myval
from MyTable
where Number = #Number
OR (NOT EXISTS(SELECT * FROM MyTable WHERE Number = #Number) AND Number = 999)
SELECT id, Myval
FROM MyTable
WHERE id = #id
UNION
SELECT id, 999 AS Myval
FROM MyTable
WHERE id = 999
AND #id IS NULL;

SQL retrieval from tables

I have a table something like
EMPLOYEE_ID DTL_ID COLUMN_A COLUMN_B
---------------------------
JOHN 0 1 1
JOHN 1 3 1
LINN 0 1 12
SMITH 0 9 1
SMITH 1 11 12
It means for each person there will be one or more records with different DTL_ID's value (0, 1, 2 .. etc).
Now I'd like to create a T-SQL statement to retrieve the records with EMPLOYEE_ID and DTL_ID.
If the specified DTL_ID is NOT found, the record with DTL_ID=0 will be returned.
I know that I can achieve this in various ways such as checking if a row exists via EXISTS or COUNT(*) first and then retrieve the row.
However, I'd like to know other possible ways because this retrieval statement is very common in my application and my table have hundred thousand of rows.
In the above approach, I've had to retrieve twice even if the record with the DTL_ID specified exists, and I want to avoid this.
Like this:
SELECT *
FROM table
WHERE EMPLOYEE_ID = ?? AND DTL_ID = ??
UNION
SELECT *
FROM table
WHERE EMPLOYEE_ID = ?? AND DTL_ID = 0
AND NOT EXISTS (SELECT *
FROM table
WHERE EMPLOYEE_ID = ?? AND DTL_ID = ??)
You will of course have to fill in the ?? with the proper number.
If DTL_ID is always 0 or positive:
SELECT TOP 1 * FROM table
where EmployeeID = #EmployeeID and DTL_ID in (#DTL_ID,0)
order by DTL_ID desc
If you're working across multiple employees in a single query, etc, then you might want to use ROW_NUMBER() if your version of SQL supports it.
Use ISNULL(DTL_ID, 0) in your final SELECT query
SELECT E1.EMPLOYEE_ID, ISNULL(E2.DTL_ID, 0), E1.COLUMN_A, E1.COLUMN_B EMPLIYEES AS E1
LEFT JOIN EMPLIYEES AS E2
ON E1.EMPLOYEE_ID = E2.EMPLOYEE_ID AND E2.DTL_ID = 42
You can use top and union, e.g.:
declare #t table(id int, value int, c char)
insert #t values (1,0,'a'), (1,1,'b'), (1,2,'c')
declare #id int = 1;
declare #value int = 2;
select top(1) *
from
(
select *
from #t t
where t.value = #value and t.id = #id
union all
select *
from #t t
where t.value = 0
)a
order by a.value desc
If #value = 2 than query returns 1 2 c. If #value = 3 than query returns 1 0 a.
SELECT MAX(DTL_ID) ...
WHERE DTL_ID IN (#DTL_ID, 0)