Select in the IF condition statement [duplicate] - sql

This question already has an answer here:
Oracle Select Statement in IF condition
(1 answer)
Closed 9 years ago.
I want to put in the if condition select query:
IF ( 10 in (select id from ids where ..) ) then ...
/* */
END IF;
How can implement that in the correct syntax ?

If you're using SQL Server then the obvious way is to use EXISTS, e.g.
if exists(select id from ids where id = 10)
begin
print 'it exists'
end
An alternative is to use the equivalent keywords SOME or ANY
if 10 = some(select id from ids)
begin
print 'it exists'
end

This may help - all examples are equiv to IF in Oracle SQL.
CASE Expressions:
SELECT deptno, empno, ename
, (CASE WHEN deptno = 10 THEN 1 ELSE 0 END) check_dept
FROM scott.emp
ORDER BY 1
/
DECODE() function:
SELECT deptno, empno, ename, DECODE(deptno, 10, 1, 0) check_dept
FROM scott.emp
ORDER BY 1
/
Your example - CASE..:
select id, (CASE WHEN id = 10 THEN 1 ELSE 0 END) AS check_id from ids where...
/

for ( --
-- The following select statement returns
-- records only, if there are any whose
-- ID = 10.
-- The rownum = 1 condition makes sure that
-- at most one record is returned.
--
select null
from ids
where id = 10 and
rownum = 1) loop
/*
Do something if at least on record is selected
by the select statement.
*/
end loop;
While this "solution" should do what you want, I don't necessarily recommend to do it like so because it might not be intrinsically clear for a later maintainer of the code what the purpose if this for ... loop exactly was. You might want to consider using a variable into which you select the count of the records with id=10 and do your thing based upon cnt>0.

Related

COUNT vs SELECT in SQL

What is better approach to check existence of an object in database?
select count(id) as count from my_table where name="searchedName";
OR
select id from my_table where name="searchedName";
And then check if count > 0 or the object is not null (ORM logic)
EDIT:
select id to be valid for Oracle.
The idea should be to that we only need to find one record in order to say that such record exists. This can be done with an EXISTS clause in standard SQL.
select exists (select * from mytable where name = 'searchedName');
returns true if the table contains a record with 'searchedName' and false otherwise.
If you want 0 for false and 1 for true instead (e.g. if the DBMS does not support booleans):
select case when exists (select * from mytable where name = 'searchedName')
then 1 else 0 end as does_exist;
You say you want this for Oracle. In Oracle you can use above query, but you'd have to select from the table dual:
select case when exists (select * from mytable where name = 'searchedName')
then 1 else 0 end as does_exist
from dual;
But for Oracle we'd usually use rownum instead:
select count(*) as does_exist
from mytable
where name = 'searchedName'
and rownum = 1; -- to find one record suffices and we'd stop then
This also returns 1 if the table contains a record with 'searchedName' and 0 otherwise. This is a very typical way in Oracle to limit lookups and the query is very readable (in my opinion).
I'd just call:
select id from my_table where name='searchedName';
Making sure there is an index for the name column.
And then check whether or not the result is empty.
Try with IF EXISTS (
if exists (select 1 from my_table where name = "searchedName")
begin
....
end

Is it possible to force reutrn value from query when no rows found? [duplicate]

This question already has answers here:
Return a value if no record is found
(6 answers)
Get 0 value from a count with no rows
(6 answers)
Closed 7 years ago.
I have a simple query:
Select qty from X where id=....;
this query always return 0 or 1 row.
when it return 1 row everything works.
but if it return 0 rows my query fails as qty is used in calculations. (This is acatually a Sub query in Select statment).
I need somehow to make sure the query always return 1 row.
I tried:
Select coalesce(qty,0) from X where id=....;
but it doesn't help as if there are no rows the coalesce is useless.
if no row found it should give 0
How can I fix it?
You can do this:
SELECT COALESCE( (SELECT qty from X where id=....), 0)
if nothing is returned from the inner SELECT statement, COALESCE will give you 0 in the outer SELECT statement.
Select *.a from (
Select qty, 0 as priority from X where id=....
Union
Select 0, 1 as priority
) a
Order By a.priority Asc
Limit 1
This select basically ensures that at least one row is returned by adding an additional row to the end and by adding the limit statement we just return the first row.
So now there is the case where at least one row is found and the additional row is added to the end. In this case the first row found (see ->) will be returned due to the ascending order by priority:
qty priority
-> 1 0
3 0
4 0
. .
0 1
And then there is the case where no row is found but the additional row is returned:
qty priority
-> 0 1
try this.
SELECT COALESCE((SELECT qty
FROM x
WHERE id = #MyIdVar), 1)
If no records found then its return 'No rows found'
if not exists(Select * from table where condition=...)
Begin
Select * from table where condition=...
End
Else
Begin
Select 'No rows found'
End
Whenever you use this you will get record else no record found message.
Without using COALESCE()
select qty from X where id=1 UNION SELECT 0 order by qty desc limit 1
Demo

What's the most efficient way to check if a record exists in Oracle?

A)
select decode(count(*), 0, 'N', 'Y') rec_exists
from (select 'X'
from dual
where exists (select 'X'
from sales
where sales_type = 'Accessories'));
B)
select decode(count(*), 0, 'N', 'Y') rec_exists
from (select 'X'
from sales
where sales_type = 'Accessories');
C) Something else (specify)
EDIT: It was hard to pick the "correct" answer, as the best approach depends on what you want to do after checking if the value exists, as pointed out by APC. I ended up picking the answer by RedFilter, since I had originally envisioned this check as a function by itself.
select case
when exists (select 1
from sales
where sales_type = 'Accessories')
then 'Y'
else 'N'
end as rec_exists
from dual;
What is the underlying logic you want to implement? If, for instance, you want to test for the existence of a record to determine to insert or update then a better choice would be to use MERGE instead.
If you expect the record to exist most of the time, this is probably the most efficient way of doing things (although the CASE WHEN EXISTS solution is likely to be just as efficient):
begin
select null into dummy
from sales
where sales_type = 'Accessories'
and rownum = 1;
-- do things here when record exists
....
exception
when no_data_found then
-- do things here when record doesn't exists
.....
end;
You only need the ROWNUM line if SALES_TYPE is not unique. There's no point in doing a count when all you want to know is whether at least one record exists.
select count(1) into existence
from sales where sales_type = 'Accessories' and rownum=1;
Oracle plan says that it costs 1 if seles_type column is indexed.
here you can check only y , n
if we need to select a name as well that whether this name exists or not.
select name , decode(count(name),0, 'N', 'Y')
from table
group by name;
Here when it is Y only then it will return output otherwise it will give null always. Whts ths way to get the records not existing with N like in output we will get Name , N. When name is not existing in table
Simply get a count of the record(s) you're looking for. If count > 0 then record(s) exist.
DECLARE
rec_count NUMBER := 0;
BEGIN
select count(*)
into rec_count
from EMPLOYEETABLE
WHERE employee_id = inEMPLOYEE_ID
AND department_nbr = inDEPARTMENT_NBR;
if rec_count > 0 then
{UPDATE EMPLOYEETABLE}
else
{INSERT INTO EMPLOYEETABLE}
end if;
END;
select decode(count(*), 0, 'N', 'Y') rec_exists
from sales
where sales_type = 'Accessories';
select NVL ((select 'Y' from dual where exists
(select 1 from sales where sales_type = 'Accessories')),'N') as rec_exists
from dual
1.Dual table will return 'Y' if record exists in sales_type table
2.Dual table will return null if no record exists in sales_type table and NVL will convert that to 'N'
The most efficient and safest way to determine if a row exists is by using a FOR-LOOP...
You won't even have a difficult time if you are looking to insert a row or do something based on the row NOT being there but, this will certainly help you if you need to determine if a row exists. See example code below for the ins and outs...
If you are only interested in knowing that 1 record exists in your potential multiple return set, than you can exit your loop after it hits it for the first time.
The loop will not be entered into at all if no record exists. You will not get any complaints from Oracle or such if the row does not exist but you are bound to find out if it does regardless. Its what I use 90% of the time (of course dependent on my needs)...
EXAMPLE:
DECLARE
v_exist varchar2(20);
BEGIN
FOR rec IN
(SELECT LOT, COMPONENT
FROM TABLE
WHERE REF_DES = (SELECT REF_DES FROM TABLE2 WHERE ORDER = '1234')
AND ORDER = '1234')
LOOP
v_exist := "IT_EXISTS"
INSERT INTO EAT_SOME_SOUP_TABLE (LOT, COMPONENT)
VALUES (rec.LOT, rec.COMPONENT);**
--Since I don't want to do this for more than one iteration (just in case there may have been more than one record returned, I will EXIT;
EXIT;
END LOOP;
IF v_exist IS NULL
THEN
--do this
END IF;
END;
--This is outside the loop right here The IF-CHECK just above will run regardless, but then you will know if your variable is null or not right!?. If there was NO records returned, it will skip the loop and just go here to the code you would have next... If (in our case above), 4 records were returned, I would exit after the first iteration due to my EXIT;... If that wasn't there, the 4 records would iterate through and do an insert on all of them. Or at least try too.
By the way, I'm not saying this is the only way you should consider doing this... You can
SELECT COUNT(*) INTO v_counter WHERE ******* etc...
Then check it like
if v_counter > 0
THEN
--code goes here
END IF;
There are more ways... Just determine it when your need arises. Keep performance in mind, and safety.
select CASE
when exists (SELECT U.USERID,U.USERNAME,U.PASSWORDHASH
FROM TBLUSERS U WHERE U.USERID =U.USERID
AND U.PASSWORDHASH=U.PASSWORDHASH)
then 'OLD PASSWORD EXISTS'
else 'OLD PASSWORD NOT EXISTS'
end as OUTPUT
from DUAL;
Another solution:
There are lot of solutions I saw in SO, which are good, count(1) or count(*) , when exists, where exists, left join, loop with no data exception..
I prefer below options, hope this is performant in large data, didn't check though :) :
Return 1 or 0 ( Can be used if you have checks with a number variable )
SELECT NVL(MIN(1),0)
FROM SALES
WHERE SALES_TYPE = 'ACCESSORIES' AND ROWNUM = 1
Return Y or N ( Can be used if you have checks with a string variable )
SELECT DECODE(MIN(1),1, 'Y', 'N')
FROM SALES
WHERE SALES_TYPE = 'ACCESSORIES' AND ROWNUM = 1
There are multiple options, Kindly do a performance test for your scenario and choose the best option.
SELECT 'Y' REC_EXISTS
FROM SALES
WHERE SALES_TYPE = 'Accessories'
The result will either be 'Y' or NULL.
Simply test against 'Y'

Order by Maximum condition match

Please help me to create a select query which contains 10 'where' clause and the order should be like that:
the results should be displayed in order of most keywords(where conditions) matched down to least matched.
NOTE: all 10 condition are with "OR".
Please help me to create this query.
i am using ms-sql server 2005
Like:
Select *
from employee
where empid in (1,2,4,332,434)
or empname like 'raj%'
or city = 'jodhpur'
or salary >5000
In above query all those record which matches maximum conditions should be on top and less matching condition record should be at bottom.
SELECT *
FROM (SELECT (CASE WHEN cond1 THEN 1 ELSE 0 END +
CASE WHEN cond2 THEN 1 ELSE 0 END +
CASE WHEN cond2 THEN 1 ELSE 0 END +
...
CASE WHEN cond10 THEN 1 ELSE 0 END
) AS numMatches,
other_columns...
FROM mytable
) xxx
WHERE numMatches > 0
ORDER BY numMatches DESC
EDIT: This answer was posted before the question was modified with a concrete example. Marcelo's solution addresses the actual problem. On the other hand, my answer was giving priority to matches of specific fields.
You may want to try something like the following, using the same expressions in the ORDER BY clause as in your WHERE clause:
SELECT *
FROM your_table
WHERE field_1 = 100 OR
field_2 = 200 OR
field_3 = 300
ORDER BY field_1 = 100 DESC,
field_2 = 200 DESC,
field_3 = 300 DESC;
I've recently answered a similar question on Stack Overflow which you might be interested in checking out:
Is there a SQL technique for ordering by matching multiple criteria?
There are many options/answers possible. Best answer depends on size of the data, non-functional requirements, etc.
That said, what I would do is something like this (easy to read / debug):
Select * from
(Select *, iif(condition1 = bla, 1, 0) as match1, ..... , match1+match2...+match10 as totalmatchscore from sourcetable
where
condition1 = bla or
condition2 = bla2
....) as helperquery
order by helperquery.totalmatchscore desc
I could not get this to work for me on Oracle.
If using oracle, then this Order by Maximum condition match is a good solution.
Utilizes the case when language feature

Check that all rows match a given criterion

requestId Consultantid statusid
1 2 10
2 2 10
3 2 10
I want to check if every row has a statusid of 10.
if (every row has a statusid of 10) then
-----do this
endif;
I'm a bit rusty on PL-SQL, but something like this would work in T-SQL:
if not exists (select * from your_table where statusid <> 10) then
-- whatever
end
Edit:
Ok, apparantly in PL-SQL, you need to do something like this:
DECLARE
notallten INTEGER;
BEGIN
SELECT COUNT(*) INTO notallten
FROM your_table
WHERE statusid <> 10
AND ROWNUM = 1;
IF notallten = 0 THEN
-- Do something
END IF;
END;
I don't have an Oracle server to test on though.
declare
v_exists_status_10 number(1);
...
begin
...
-- v_exists_status_10 = 0 if no such row exist, 1 if at least one does
select count(*)
into v_exists_status_10
from dual
where exists
(select * from your_table where statusid <> 10);
if v_exists_status_10 > 0 then
...
Note that you could also do a dumb COUNT() into a variable, but it could be massively inefficient compared to EXISTS. With a COUNT() you'd have to scan all the records, whereas with an EXISTS as soon as it hits a statusid = 10 it can stop scanning.
Simpler solution, that accounts for NULLs in statusid:
for r in (
select 1 dummy
from your_table
where (statusid != 10 or statusid is null)
and rownum = 1) loop
-----do this
end loop;