Left join to same table SQL - sql

I am trying to make a left join to the same table in the same query but the result is not okey, I resolved the problem with a subquery this is the wrong query:
SELECT * FROM TableA ta
LEFT JOIN TableA Lta ON ta.key = Lta.key
AND ta.state IN('C')
AND Lta.state IN ('A','E')
WHERE Lta.key is null
This is the way how I resolved
SELECT * FROM (
SELECT * FROM TableA ta
WHERE ta.state IN('C')
) AS T LEFT JOIN TableA Lta ON T.key = Lta.key
AND Lta.state in ('A','E')
WHERE Lta.key IS NULL
I am a little confused with those queries if you can give me some information related to this topic I will be so grateful to you
Thank you

You were very close in your first query. Move the "ta.state" to the where clause. The join is how the two tables relate but secondary criteria on JUST the "lta" alias.
SELECT
*
FROM
TableA ta
LEFT JOIN TableA Lta
ON ta.key = Lta.key
AND Lta.state IN ('A','E')
WHERE
ta.state IN('C')
AND Lta.key is null
So your primary criteria is WHERE the ta.state is "C", but then only if there is NOT a match for the "A" and "E" instances in the second (left-join) alias of lta

For "not-existance" checking case I strongly recommend you to use not exists subquery:
SELECT * FROM TableA ta
WHERE not exists
(
SELECT 1 FROM TableA Lta
WHERE ta.key = Lta.key
AND ta.state IN('C')
AND Lta.state IN ('A','E')
)
this is the most performance-friendly approach.
Not sure but it's likely that you should move ta.state = 'C' to the outer where clause.

Related

Re-Writing a SQL Statement with a Subquery to Have a Join

I have to re-write a SQL statement with a subquery so that it has a join for my job. So far, this is what I have.
SELECT * FROM Table_A
WHERE TABLE_A.A_ID NOT IN
(SELECT LK.A_ID FROM Link_Table LK
LEFT JOIN Table_B B
ON B.B_ID = LK.B_ID)
I am really having a hard time with this. I feel like this is because of the link tables though. Can anyone give me advice on altering this query?
Seems like you want a LEFT JOin with a IS NULL in the where:
SELECT {Column list} --Don't use *
FROM dbo.Table_A A
LEFT JOIN dbo.Link_Table LK ON A.A_ID = LK.A_ID
WHERE LK.A_ID IS NULL;
You don't need the reference to Table_B at all here.
Personally, however, I would prefer an EXISTS, but that is a subquery again:
SELECT {Column List}
FROM dbo.Table_A A
WHERE NOT EXISTS (SELECT 1
FROM dbo.Link_Table LK
WHERE A.A_ID = LK.A_ID);

SQL Query to compare columns in different table

I have TableA and TableB which contains identical columns but they have different records.
How do I find out which "UniqueID" is not in TableA but in TableB?
I have been doing
select tc.uniqueid, td.uniqueid
from tab1c as tc
left join tab2c as td
where tc.uniqueid != td.uniqueid;
but it doesnt seem to be correct.
Use left join:
select tc.uniqueid, td.uniqueid
from tab1c as tc
left join tab2c as td
on tc.uniqueid = td.uniqueid
where td.uniqueid = NULL; --Will get all uid in tab1c and not in tab2c
The same efficient and more readability way is NOT EXISTS:
select tc.uniqueid
from tab1c as tc
WHERE NOT EXISTS (SELECT * FROM tab2c as td
WHERE tc.uniqueid = td.uniqueid)
The below query will find all the unique id`s which is not there in tableA
SELECT UNIQUEID FROM TABLEB WHERE UNIQUEID NOT IN (SELECT DISTINCT UNIQUEID FROM TABLEA);
Maybe not the most efficient way but you can use EXCEPT
SELECT UNIQUEID
FROM tab1c
EXCEPT
SELECT UNIQUEID
FROM tab2c

Using subqueries in PostgreSQL

I'm only about a day into using PostgreSQL and have what is pry a quite simple question. I want to create a left outer join to search for mismatch values. I'd like from the join create a subquery which selects the null values and then updates are based on this selection. What I have for the left outer join looks like this:
SELECT TableA.field1, TableA.field2, TableB.field3
FROM
TableA
LEFT OUTER JOIN TableB ON TableA.field1 = TableB.field1
This works for the join. However, I can't manage to figure out how to then use a subquery to return only rows where TableB.field1 is null.
You don't need a subquery:
SELECT TableA.field1, TableA.field2, TableB.field1
FROM TableA
LEFT OUTER JOIN TableB ON TableA.field1 = TableB.field1
where tableB.field1 IS NULL;
Not sure what you mean with "and then updates a based on this selection" though
Here is how you ...
Select rows which are not present in other table
I suppose you want to update rows based on this selection. Use the FROM clause to join more (derived) tables in an UPDATE:
UPDATE some_table t
SET (field1, field2, field3)
= (a.field1, a.field2, a.field3)
FROM (
SELECT a.a_id, a.field1, a.field2, a.field3
FROM tablea a
LEFT JOIN tableb b USING (field1)
WHERE b.field1 IS NULL
) a
WHERE t.a_id = a.a_id; -- join on the connecting column
Using the short syntax variant to update multiple columns.

SQL join with case

How can I modify the join clause with a case clause; for example I want the table to join another column if column1 is null such as:
SELECT * FROM MYTABLE
LEFT JOIN OTHERTABLE ON
CASE WHEN MYTABLE.A IS NULL THEN MYTABLE.B = OTHERTABLE.A
ELSE MYTABLE.A IS NOT NULL THEN MYTABLE.A = OTHERTABLE.A
(totally made that up,sorry for syntax errors :))
Try this one:
SELECT *
FROM MyTable M
LEFT JOIN OtherTable O ON(CASE WHEN M.A IS NULL THEN M.B ELSE M.A END) = O.A
SELECT * FROM MYTABLE
LEFT JOIN OTHERTABLE ON COALESCE(MYTABLE.A, MYTABLE.B) = OTHERTABLE.A
Just try below code :
SELECT * FROM MYTABLE
LEFT JOIN OTHERTABLE ON OTHERTABLE.A = isnull(MYTABLE.A,MYTABLE.B)
You can use isnull() or coalesce() to check the null value.

Is it possible to use IF or CASE in sql FROM statement

I have a long stored procedure and I would like to make a slight modification to the procedure without having to create a new one(for maintenance purposes).
Is it possible to use a IF or CASE in the FROM statement of the select statement to join other tables?
Like this:
from tableA a
join tableB b a.indexed = c.indexed
IF #Param='Y'
BEGIN
join tableC c a.indexed = c.indexed
END
It didn't seem to work for me. But I am wondering if this is even possible and/or if this even makes sense to do.
Thanks.
No, it is not possible. You can only accomplish this through the use of dynamic SQL.
The Curse and Blessings of Dynamic SQL
An Intro to Dynamic SQL
I would not advise using Dynamic SQL, there are most likely better ways to perform this operation but you would have to provide more info.
You can achieve something like it if you have a left outer join
Consider
declare #param bit = 1
select a.*, b.*, c.* from a
inner join b on a.id = b.a_id
left outer join c on b.id = c.b_id and #param = 1
This will return all columns from a, b, c.
Now try with
declare #param bit = 0
This will return all columns from a and b, and nulls for columns of c.
It won't work if both joins are inner.
No this is not possible. Your best bet would probably be to select from both tables and only include the data your care about. If you provide an example of what you are trying to do I can provide a better answer.
Attempt at an example:
SELECT t1.id, COALESCE(t2.name, t3.name)
FROM Table1 as t1
LEFT JOIN Table2 as t2
ON t1.id = t2.id
LEFT JOIN Table2 as t3
ON t1.id = t3.id
While what you proposed is not possible, you can play with your where conditions:
from tableA a
inner join tableB b ON a.indexed = c.indexed
left join tableC c ON a.indexed = c.indexed AND 1 = CASE #Param WHEN 'Y' THEN 1 ELSE 0 END
More performant would be to just doing a big
IF #Param='Y' THEN
from tableA a
inner join tableB b ON a.indexed = c.indexed
ELSE
from tableA a
inner join tableB b ON a.indexed = c.indexed
left join tableC c ON a.indexed = c.indexed
You haven't revealed you SELECT clause. The essence of what you want is as follows:
SELECT indexed
FROM tableA
INTERSECT
SELECT indexed
FROM tableB
INTERSECT
SELECT indexed
FROM tableC
WHERE #Param = 'Y'
Then use this table expression as dictated by your SELECT clause e.g. say you only want to project tableA:
WITH T
AS
(
SELECT indexed
FROM tableA
INTERSECT
SELECT indexed
FROM tableB
INTERSECT
SELECT indexed
FROM tableC
WHERE #Param = 'Y'
)
SELECT *
FROM tableA
WHERE indexed IN ( SELECT indexed FROM T );