How to do a left join on a run-time generated tables? - sql

I have two tables in the database (myCustomTable1 and myCustomTable2) and from them I'm creating another two tables (Table1 and Table2) which are created during the run time. Now I need to take the rows which are inside of Table1, but are not in the Table2.
I found this question, which seems that contains the answer that I need, but I'm not able to implement this with my solution, because as said, tables which I need to "antijoin" are generated during run-time.
Both of my (run-time generated) tables have the format:
-----------------------
| Column1 | Column2 |
-----------------------
| | |
-----------------------
| | |
-----------------------
Here is the code that I have.
SELECT Table1.* FROM (
SELECT myCustomTable1.Column1,
myCustomTable1.Column2
) as Table1
LEFT JOIN
(
SELECT Table2.* FROM (
SELECT myCustomTable2.Column1,
myCustomTable2.Column2
) as Table2
)
ON Table1.Column1 = Table2.Column1
AND Table1.Column2 = Table2.Column2
Now I'm aware that this solution is not working, because when trying to join, I'm trying to use Table2, which is not available in the global scope, but I can not find any appropriate solution.
Maybe using NOT EXISTS, LEFT OUTER JOIN or NOT IN is also an option, but in every try, I faced with the same issue where the scope of the defined tables is a problem.

I find it a lot easier to separate your sets in CTEs:
;WITH Table1 AS
(
SELECT
myCustomTable1.Column1,
myCustomTable1.Column2
FROM
myCustomTable1
),
Table2 AS
(
SELECT
myCustomTable2.Column1,
myCustomTable2.Column2
FROM
myCustomTable2
)
SELECT *
FROM Table1 as t1
WHERE
NOT EXISTS (SELECT 1
FROM Table2 as t2
WHERE t1.Column1 = t2.Column1
AND t1.Column2 = t2.Column2);

You missed a from table in the inner suquery and a table alias in the outer left join try use
SELECT Table1.* FROM (
SELECT myCustomTable1.Column1,
myCustomTable1.Column2
) as Table1
LEFT JOIN
(
SELECT Table2.* FROM (
SELECT myCustomTable2.Column1,
myCustomTable2.Column2
FROM myCustomTable2
) as Table2
) as table 3
ON Table1.Column1 = Table3.Column1
AND Table1.Column2 = Table3.Column2

You can select the records from Table1 excluding the matches using not exists in the where:
select *
from Table1
where
not exists(select 1
from Table2
where Table1.Column1 = Table2.Column1 and Table1.Column2 = Table2.Column2);

If you meant the aliases Table1 and Table2 as runtime created wouldn't this work?:
SELECT Table1.*
FROM (
SELECT myCustomTable1.Column1,
myCustomTable1.Column2
) as Table1
LEFT JOIN
(
SELECT myCustomTable2.Column1,
myCustomTable2.Column2
) as Table2
ON Table1.Column1 = Table2.Column1
AND Table1.Column2 = Table2.Column2
where Table2.Column1 is null;
Or (better IMHO):
SELECT Column1,
Column2
from myCustomTable1 t1
where not exists
(
SELECT * from myCustomTable2 t2 where
t1.Column1 = t2.Column1 and t1.Column2 = t2.Column2
);

Related

SQL LEFT JOIN with WHERE class

there are two tables TABLE1 and TABLE2 in TABLE1 there are records which does not exist in TABLE2 with left join below i wanted to query all records which are in TABLE1 if the record does not exist in table2 however.
Note: about WHERE class in my code that is required this is because, there can be several records in the name of 'IN PROGRESS' in TABLE2 with one record in the name of 'GRADUATED' i wanted to distinct records based on table 1 ID that if there is any record in the name of 'GRADUATE' it should show only that else it should show inprogress.
SELECT DISTINCT
TABLE1.ID,
TABLE2.TRAINING_STATUS_CHECK
FROM TABLE1
LEFT JOIN TABLE2
ON TABLE1.ID = TABLE2.FK_ID_CLASS
WHERE NOT EXISTS
(
SELECT DISTINCT
TABLE1.ID,
TABLE2.TRAINING_STATUS_CHECK
FROM TABLE1
LEFT JOIN TABLE2
ON TABLE1.ID = TABLE2.FK_ID_CLASS
WHERE TABLE2.TRAINING_STATUS_CHECK = 'GRADUATED')
OR TABLE2.TRAINING_STATUS_CHECK = 'GRADUATED'
I see some odds with your query:
exists part are not related with you main query. I think you need some relation
distinct in part not exists are not needed
You filter columns with the same conditions as filter main row set
As I understand you want to get all rows from table1 with state 'GRADUATED' int table2 and any row from table1 where rows in table2 are not exists or state not equal 'GRADUATED'
SELECT DISTINCT
t1.ID,
t2.TRAINING_STATUS_CHECK
FROM TABLE1 t1
LEFT JOIN TABLE2 t2 ON t1.ID = t2.FK_ID_CLASS
WHERE NOT EXISTS
(
SELECT NULL /*its not nesessary what you need*/
FROM TABLE1 sub_t1
JOIN TABLE2 sub_t2 ON sub_t1.ID = sub_t2.FK_ID_CLASS /* left join replaced to inner */
WHERE sub_t2.TRAINING_STATUS_CHECK = 'GRADUATED'
AND sub_t1.ID = t1.ID /*relation with outer query*/
)
OR t2.TRAINING_STATUS_CHECK = 'GRADUATED'
where the relatonship between tables does not exist - but only if the comparison involves rows in table that are not 'graduated' (I think)
SELECT DISTINCT
TABLE1.ID,
TABLE2.TRAINING_STATUS_CHECK
FROM TABLE1
LEFT JOIN TABLE2 ON TABLE1.ID = TABLE2.FK_ID_CLASS
AND TABLE2.TRAINING_STATUS_CHECK <> 'GRADUATED'
WHERE TABLE2.FK_ID_CLASS IS NULL
Not sure about your question but if you want all the records from table 1 who are not in table 2, you just have to do this :
SELECT TABLE1.ID
FROM TABLE1
LEFT JOIN TABLE2 ON TABLE1.ID = TABLE2.FK_ID_CLASS
WHERE TABLE2.FK_ID_CLASS IS NULL
Try this:
SELECT DISTINCT TABLE1.ID, TABLE2.TRAINING_STATUS_CHECK
FROM TABLE1
LEFT JOIN TABLE2
ON TABLE1.ID = TABLE2.FK_ID_CLASS
AND (NOT EXISTS (SELECT 1
FROM TABLE2 t
WHERE TABLE1.ID = t.FK_ID_CLASS
AND t.TRAINING_STATUS_CHECK = 'GRADUATED')
OR TABLE2.TRAINING_STATUS_CHECK = 'GRADUATED')
For the record, conditions on the right table of a LEFT JOIN need to be placed inside the ON() clause or the join will transfer into an INNER JOIN due to NULL comparison.
It seems to me you have three distinct cases that can be "ORed together" using UNION; personally I find keeping all three separated like this makes things much easier to read and understand:
--- ID with GRADUATED exists in TABLE2
( SELECT ID, 'GRADUATED' AS TRAINING_STATUS_CHECK
FROM TABLE1
INTERSECT
SELECT FK_ID_CLASS, 'GRADUATED'
FROM TABLE2
WHERE TRAINING_STATUS_CHECK = 'GRADUATED' )
UNION
--- ID without GRADUATED exists in TABLE2
( SELECT ID, 'IN PROGRESS'
FROM TABLE1
MINUS
SELECT FK_ID_CLASS, 'IN PROGRESS'
FROM TABLE2
WHERE TRAINING_STATUS_CHECK = 'GRADUATED' )
UNION
--- ID does not exist in TABLE2
( SELECT ID, '{{NONE}}'
FROM TABLE1
WHERE ID NOT IN ( SELECT FK_ID_CLASS FROM TABLE2 ) );

Applying joins conditionally in SQL Server

I have some set of records, but now i have to select only those records from this set which have theeir Id in either of the two tables.
Suppose I have table1 which contains
Id Name
----------
1 Name1
2 Name2
Now I need to select only those records from table one
which have either their id in table2 or in table3
I was trying to apply or operator witin inner join like:
select *
from table1
inner join table2 on table2.id = table1.id or
inner join table3 on table3.id = table1.id.
Is it possible? What is the best method to approach this? Actually I am also not able to use
if exist(select 1 from table2 where id=table1.id) then select from table1
Could someone help me to get over this?
Use left join and then check if at least one of the joins has found a relation
select t1.*
from table1 t1
left join table2 t2 on t2.id = t1.id
left join table3 t3 on t3.id = t1.id
where t2.id is not null
or t3.is is not null
I would be inclined to use exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.id = t1.id) or
exists (select 1 from table3 t3 where t3.id = t1.id) ;
The advantage to using exists (or in) over a join involves duplicate rows. If table2 or table3 have multiple rows for a given id, then a version using join will produce multiple rows in the result set.
I think the most efficient way is to use UNION on table2 and table3 and join to it :
SELECT t1.*
FROM table1 t1
INNER JOIN(SELECT id FROM Table2
UNION
SELECT id FROM Table3) s
ON(t.id = s.id)
Alternatively, you can use below SQL as well:
SELECT *
FROM dbo.Table1
WHERE id Table1.IN ( SELECT table2.id
FROM dbo.table2 )
OR Table1.id IN ( SELECT table3.id
FROM Table3 )

SQL using minus function to eliminate rows from specific columns but returning all columns from table

I'm trying to return all columns in a database where certain rows within certain columns have been eliminate. Is there any possible way to do this? I tried using code like this but I'm unsure what I am missing to make this work
Select * from table1
where (select column1 from table1
minus select column1 from table2);
You can do this with a WHERE NOT EXISTS:
Select T1.*
From Table1 T1
Where Not Exists
(
Select *
From Table2 T2
Where T2.Column1 = T1.Column1
)
Alternatively, you could use a LEFT OUTER JOIN:
Select T1.*
From Table1 T1
Left Join Table2 T2 On T2.Column1 = T1.Column1
Where T2.Column1 Is Null
Or even a WHERE NOT IN:
Select *
From Table1
Where Column1 Not In
(
Select Column1
From Table2
)
I would recommend the WHERE NOT EXISTS approach, but to fix the query you have in the question, you just need to add a WHERE IN:
Select *
From Table1
Where Column1 In
(
Select Column1
From Table1
Minus
Select Column1
From Table2
)
Try this:
select * from table1 where column1 in
(select column1 from table1
minus
select column1 from table2);

Transform select count(*) inside a inner join

My problem here is that i'm modifying an existing query and i cannot use count(*) in the query.
I have to use inner join subqueries.
What i need to "transform" into my inner join is like this (this works):
SELECT count(distinct t1.id)
FROM table1 t1
WHERE t1.column1 = 'value1' AND
t2.column2 = 'value2' AND
EXISTS(select 1 from table2 t2 where t2.id = t1.id)
My global query looks like this:
SELECT [many many column]
FROM table2 t2
INNER JOIN [...]
LEFT OUTER JOIN [...]
--[I NEED MY COUNT HERE, see below for example]
WHERE [some conditions are true]
ORDER BY [some column]
What i found to help me is something like this:
SELECT [many many column], myJoin.Count
FROM table2 t2
INNER JOIN (
SELECT tt2.id, count(distinct tt2.id) as Count
FROM table2 tt2
WHERE EXISTS (SELECT 1 FROM table1 tt1 where tt1.id = tt2.id)
GROUP BY tt2.id) myJoin
on t2.id = myJoin.id;
See what i'm trying to acheive? I need to count the ids, joining 2 tables, but i can't have a count in my main query, i can't possibly copy-paste all the "group by" condition that would go with it...
I'm on sql server.
If i find the answer i will come back and post it.
Thanks for any advice/tricks about this.
How about the following:
SELECT table2.*, TopQ.MyCount
FROM (
SELECT t2.id, myJoin.MyCount
FROM table2 t2
INNER JOIN (
SELECT tt2.id, count(distinct tt2.id) as MyCount
FROM table2 tt2
WHERE EXISTS
(SELECT 1 FROM table1 tt1 where tt1.id = tt2.id)
GROUP BY tt2.id) AS myJoin
on t2.id = myJoin.id
)AS TopQ
INNER JOIN table2 ON TopQ.id = table2.id
I came across this:
select count(distinct t1.id) over (partition by t1.aColumn) as myCount,
[many many column]
from table2 t2
inner join table1 t1 on [someConditions] = value1 and
[someConditions] = value2 and
t2.id = t1.id;
I get the same results as my first select i posted in my question, and without adding a "group by" anywhere and a lot of inner join that im not that familliar with. I'm gonna stick with this solution.
Thanks!

mysql join two tables

I have a problem joining two tables:
table1
id name
1 aaa
2 bbb
3 ccc
table2
id table1_id name
1 1 x1
2 1 x2
3 2 s1
table1 is the main table, table2 contains attributes.
I need to join and search both tables, but display distinct results from first table.
When using JOIN I get multiple results from table2.
The scenario is I need to search main table TABLE1 and ALL ATTRIBUTES in TABLE2 and return if found
select distinct(name) from table1 inner join table2 on table1.id = table2.table1_id where table2.name = x2;
Should do the trick.
If you need entries which exists in both tables:
SELECT * from Table1 t1
WHERE YourConditionsHere
AND EXISTS (SELECT 1 from Table2 t2
WHERE t1.Id = t2.Table1_id
AND YourConditionsHere)
if you need entries from Table1 for which does not exists enteries in Table2
SELECT * from Table1 t1
LEFT JOIN
(SELECT * from Table2
WHERE YourConditionsHere
) t2
ON (t1.Id = t2.Table1_id)
WHERE YourConditionsHereForTable1
another option
select * from table1 t1 where t1.id in (select table1_id from table2 t2 where t2.name = "x1");
it's probably best to check query plains (i.e. EXPLAIN) for all suggested queries and check the one that performs best for your exact scenario.