I'm trying to write select as:
SELECT * FROM table1 a
WHERE a.d > (
SELECT b.d FROM table2 b
WHERE a.id = b.id and a.Something = 1
)
BUT if the nested select does not returns any value so SELECT does not returns anything either.
Is possible to write something like:
SELECT * FROM table1 a WHERE a.d >
(SELECT * FROM
IF EXISTS (
SELECT b.d FROM table2 b WHERE a.id = b.id and a.Something = 1
)
SELECT b.d FROM table2 b WHERE a.id = b.id and a.Something = 1 )
ELSE
SELECT '0'
)
You can use COALESCE
SELECT *
FROM table1 a
WHERE a.d > COALESCE((SELECT b.d FROM table2 b WHERE a.id = b.id and a.Something = 1), '0')
COALESCE
Evaluates the arguments in order and returns the current
value of the first expression that initially does not evaluate to
NULL.
See this link for more info.
Related
I have two tables TableA and TableB. For one of the record in TableB(id =1), I want to perform join on condition1(a.value = b.value) and for other records I want to join on condition2((a.value - b.value)/ a.val < 1).
But, I am getting syntax error at end. How to apply case condition in this scenario?
Select * from TableA a
LEFT JOIN TableB b
on a.id = b.id
and (
case when b.id = 1 then a.value = b.value
else (a.value - b.value)/ a.val < 1 end
)
Just use boolean logic:
select *
from TableA a left join
TableB b
on a.id = b.id and
(b.id = 1 and a.value = b.value or
b.id <> 1 and (a.value - b.value)/ a.val < 1
)
I'm trying to teach myself and better understand alternative methods to a UNION and discover when I can use joins.
As I'm playing with this I can't seem to get what I want without a UNION. Is it possible to write this in a single query?
SELECT DISTINCT a.id
FROM table1 a, table2 b
WHERE a.id = b.id
AND a.ind IS NULL
AND b.year >= '2017'
AND b.code IN ('01','02','03')
AND b.flag NOT IN ('F','L')
UNION
SELECT DISTINCT a.id
FROM table1 a, table3 c
WHERE a.id = c.id
AND a.ind IS NULL
AND c.area = 'MAIN'
AND SYSDATE >= c.start
Thanks in advance for any guidance or help.
SELECT DISTINCT a.id
FROM table1 a
LEFT JOIN table2 b on b.id = a.id AND b.year >= '2017'
AND b.code IN ('01', '02', '03') AND b.flag NOT IN ('F', 'L')
LEFT JOIN table3 c ON a.id = c.id and c.area = 'MAIN' and SYSDATE >= c.start
WHERE a.ind IS NULL
AND ( b.id IS NOT NULL or c.id IS NOT NULL)
This is one of those things where the old obsolete A,B join syntax really shows it's age, when you have some conditions that must go in a specific ON clause and others that must go in the WHERE clause. It would be very difficult to write this query that way, and even harder to read and understand it later. Better to always write out the full INNER JOIN, LEFT JOIN, etc.
Whenever you see a distinct, resources have been wasted.
SELECT a.id
FROM table1 a
where a.ind IS NULL
and ( exists (select null from table2 b
WHERE a.id = b.id
AND b.year >= '2017'
AND b.code IN ('01','02','03')
AND b.flag NOT IN ('F','L') )
or exists (SELECT null FROM table3 c
WHERE a.id = c.id
AND c.area = 'MAIN'
AND SYSDATE >= c.startdt)
)
Indexes on table2 (id,year,code,flag) and table3 (id,area,startdt) won't hurt performance. Oracle 11gR2 did not allow me to have a column named "start".
I would use this
select a.id
from table1 a
where
a.ind is null and (
a.id in (
select b.id
from table2 b
where
b.year >= '2017'
and b.code IN ('01','02','03')
and b.flag NOT IN ('F','L')
) or
a.id in (
select c.id
from table3 c
where
c.area = 'MAIN'
and sysdate >= c.start
)
)
DISTINCT + table joins can be rewritten as IN/EXISTS most of the times. In several databases it might even select a better execution plan (e.g: Oracle)
Please let me know if using Full outer join makes sense
with cte as (
select 1 as nu union
select 2 as nu union
select 3 as nu union
select 4 as nu union
select 5 as nu union
select 6 as nu )
,cte2 as (
select 1 as nu union
select 2 as nu union
select 3 as nu )
,cte3 as (
select 7 as nu union
select 8 as nu union
select 9 as nu )
select coalesce(cte.nu,cte2.nu,cte3.nu)
from cte
full outer join cte2 on cte.nu = cte2.nu
full outer join cte3 on cte.nu = cte3.nu
Please check if this works
SELECT DISTINCT a.id
FROM table1 a, table2 b, table3 c
WHERE (a.id = b.id
OR a.id = c.id)
AND a.ind IS NULL
AND (( b.year >= '2017'
AND b.code IN ('01','02','03')
AND b.flag NOT IN ('F','L'))
OR (c.area = 'MAIN'
AND SYSDATE >= c.start))
I want the entire query to run for each value returned by the sub-query in where clause. I am unable to figure out what i am doing wrong here. Please help?
SELECT a.*, b.*, c.*
FROM table1 a, table2 b, table3 c
WHERE a.val1 = ( select val1 from table1 )
AND a.val2 = b.val3
AND a.val4 = c.val5;
in instead of =
SELECT a.*, b.*, c.*
FROM table1 a, table2 b, table3 c
WHERE a.val1 in ( select val1 from table1 )
AND a.val2 = b.val3
AND a.val4 = c.val5;
I have need a query that JOIN a TABLE with A first row of other table value based:
SELECT * FROM TABLEA A LEFT JOIN
(SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
but DB2 return ERROR because can't use A.CODE
How can solve this?
You need to use the nested table expression:
SELECT * FROM TABLEA A LEFT JOIN
LATERAL (SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
This is a highly optimized statement.
Your not getting any data from tableb and your going for first row so you just need exists clause.
select a.* from tablea a
where exists (select * from tableb b
where a.fielda = b.fielda
and a.fieldb = b.fieldb
and b.code = a.code
and b.field2 = 'd' and b.field1 <> '3')
You can use the OLAP function row_number() to rank the records according to somefield(s) within a (fielda,fieldb,code) group. Somefield might be a transaction id, or sequence, for example. The order by clause is optional there, but without it, you might be randomly picking which record is the first in the group.
WITH B AS
(SELECT *,
row_number() over (partition by fielda,fieldb,code
order by somefield
) as pick
from TABLEB
WHERE FIELD1 <> '3'
and FIELD2 = 'D'
)
SELECT *
FROM TABLEA A LEFT JOIN B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
and A.CODE = B.CODE
where pick=1
I have table A, B and C
I want to return all entries in table A that do not exist in table B and of that list do not exist in table C.
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
this gives me the first result of entries in A that are not in B. But now I want only those entries of this result that are also not in C.
I tried flavours of:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
where not exists (select 1 from table_C as c
where a.id = c.id)
But that isnt the correct logic. If there is a way to store the results from the first query and then select * from that result that are not existent in table C. But I'm not sure how to do that. I appreciate the help.
Try this:
select * from (
select a.*, b.id as b_id, c.id as c_id
from table_A as a
left outer join table_B as b on a.id = b.id
left outer join table_C as c on c.id = a.id
) T
where b_id is null
and c_id is null
Another implementation is this:
select a1.*
from table_A as a1
inner join (
select a.id from table_A
except
select b.id from table_B
except
select c.id from table_c
) as a2 on a1.id = a2.id
Note the restrictions on the form of the sub-query as described here. The second implementation, by most succinctly and clearly describing the desired operation to SQL Server, is likely to be the most efficient.
You have two WHERE clauses in (the external part of) your second query. That is not valid SQL. If you remove it, it should work as expected:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
not exists (select 1 from table_C as c -- WHERE removed
where a.id = c.id) ;
Tested in SQL-Fiddle (thnx #Alexander)
how about using LEFT JOIN
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
LEFT JOIN TableC c
ON a.ID = c.ID
WHERE b.ID IS NULL AND
c.ID IS NULL
SQLFiddle Demo
One more option with NOT EXISTS operator
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM (SELECT b.ID
FROM dbo.test72 b
UNION ALL
SELECT c.ID
FROM dbo.test73 c) x
WHERE a.ID = x.ID
)
Demo on SQLFiddle
Option from #ypercube.Thank for the present;)
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM dbo.test72 b
WHERE a.ID = b.ID
UNION ALL
SELECT 1
FROM dbo.test73 c
WHERE a.ID = c.ID
);
Demo on SQLFiddle
I do not like "not exists" but if for some reason it seems to be more logical to you; then you can use a alias for your first query. Subsequently, you can re apply another "not exists" clause. Something like:
SELECT * FROM
( select * from tableA as a
where not exists (select 1 from tableB as b
where a.id = b.id) )
AS A_NOT_IN_B
WHERE NOT EXISTS (
SELECT 1 FROM tableC as c
WHERE c.id = A_NOT_IN_B.id
)