Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have 2 tables A and B.
Table A has 3 rows and one column having values 1, 1, 1.
Table B has 2 rows and one column having values 1, 1.
Upon applying left join, Table A left join Table B
The output I will receive is:
1, 1, 1.
Is it correct?
No, your assumption is not correct. If you join on the columns you mention, you will get 6 rows (3 x 2), because every row matches each other.
Table t1
id_t1
colx
1
1
2
1
3
1
Table t2
id_t2
coly
10
1
20
1
Query
select *
from t1
left outer join t2 on t2.coly = t1.colx
order by t1.id_t1, t2.id_t2;
Result
id_t1
colx
id_t2
coly
1
1
10
1
1
1
20
1
2
1
10
1
2
1
20
1
3
1
10
1
3
1
20
1
You seem to misunderstand what a left outer join does. Each row in table t1 has two matches in table t2. You get these with a left outer join, but you also get them with an inner join. The difference between the two join types is when there is no match. Let's add another row to table t1:
id_t1
colx
4
2
There is no match in t2 for the value 2. An inner join would not show this row in the results. A left outer join in contrast will add the following row to your results:
id_t1
colx
id_t2
coly
4
2
null
null
Related
I have the following tables:
T1 T2 Desired result
CA CB CA CC CA CB
1 2 1 3 1 4
1 4 1 2 2 1
1 3 1 5 2 3
2 1 2 4
2 3
3 6
3 1
4 ...
I need to make a join between T1 and T2 (using column CA) and return only those rows which the values in CB do not exists in T2.CC
A simple way to achieve that is using the following query:
SELECT T1.* FROM T1 INNER JOIN T2 ON t1.CA = t2.CA AND
t1.CB NOT IN (SELECT CC FROM T2 WHERE T2.CA = T1.CA)
I think the previous query is not very efficient. For that reason I am looking for something better
Any help will be appreciated
Generally, a more efficient means of achieving this sort of result is finding records which fail a simpler join condition. Those can be found by doing an outer join and checking for null, as follows:
select t1.ca, t1.cb
from t1 left outer join t2 on t1.ca=t2.ca and t1.cb=t2.cc
where t2.ca is null;
I think you just want not exists:
select t1.*
from t1
where not exists (select 1
from t2
where t2.ca = t1.ca and t2.cb = t1.cb
);
For performance, you want an index on t2(ca, cb).
Why does this query produce duplicates in some scenarios?
Table_1
ID
1
2
3
Table_2
ID
1
2
4
Table_3
ID
1
3
4
Query:
SELECT COALESCE(Table_1.ID, Table_2.ID, Table_3.ID)
FROM Table_1
FULL OUTER JOIN TABLE_2
ON Table1.ID=Table_2.ID
FULL OUTER JOIN TABLE_3
ON Table1.ID=Table3.ID;
Result:
1
2
3
4
4
The query duplicates all values where T1 is null and T2/T3 share the same value. Duplicates are removed for any other combination.
This is a little bit hard to explain. If you show the other ids, you will see the full range of what happens:
"coalesce" "id1" "id2" "id3"
1 1 1 1
2 2 2 .
3 3 . 3
4 . 4 .
4 . . 4
You can see the results here.
So, You get one row because t1 & t2 create a row with t2.id = 4 and t1.id = null when they don't match. Then, you get the same thing when t3.id = 4. The comparison is to t1.id -- so you get another row. There is no comparison to t2.id.
I suspect that you intend logic more like this:
select coalesce(t1.id, t2.id, t3.id)
from t1 full join
t2
using (id) full join
t3
using (id);
Here is the SQL Fiddle.
Can anyone help to get this result in 1 sql statement?
I have 2 tables with the 2nd table having dominance over the first -- as follows:
TableA
Code | Quantity
1 5
3 5
4 5
TableB
Code | Quantity
1 5
2 1
4 6
Query Result
Code | Quantity
1 5 - code exists in both - return record from TableB
2 1 - distinct only in TableB
3 5 - distinct only in TableA
4 6 - code exists in both - return record from TableB
Appreciate your help. Thanks!
A FULL JOIN will do:
SELECT COALESCE(t1.Code, t2.Code) AS Code,
COALESCE(t2.Quantity, t1.Quantity) AS Quantity
FROM TableA AS t1
FULL OUTER JOIN TableB AS t2 ON t1.code = t2.code
COALESCE(t2.Quantity, t1.Quantity) essentially implements your requirement for 'dominance' of TableB over TableA: Quantity is picked up from TableA only in case there is no matching record in TableB.
For an explanation on how a FULL JOIN works you can have a look here:
FULL OUTER JOIN, includes all rows from both tables, regardless
of whether or not the other table has a matching value.
I have a table that contains the following columns:
ID
Master ID
The Master ID can be shared between different rows with different IDs.
E.g.:
ID | Master ID
1 | 1
2 | 1
3 | 1
4 | 2
Knowing the ID I want to retrieve all the rows that share the same master ID
I managed to do it using this query:
Select *
FROM table t
LEFT JOIN table t2
ON t.MASTER_ID = t2.MASTER_ID
Where t.ID = '1'
Then I also tried using:
Select *
FROM table t
LEFT JOIN table t2
ON t.MASTER_ID = t2.MASTER_ID and t.ID = '1'
In that case, it was much slower. Can anyone explain why?
The queries are doing different things, the first you are saying:
1. give me all rows from `table` where `id = 1`
2. Also give me rows from t2 with a matching master ID
In the second you are saying
1. Give me all rows from `table`
2. Return rows from `t2` with a matching master ID and where `t1.ID = 1`
In a simple example you might have
ID Master_ID
------------------------
1 1
2 1
3 1
4 2
So your first query will return:
t1.ID t1.Master_ID t2.ID t2.Master_ID
--------------------------------------------
1 1 1 1
1 1 2 1
1 1 3 1
Your second query will return
t1.ID t1.Master_ID t2.ID t2.Master_ID
--------------------------------------------
1 1 1 1
1 1 2 1
1 1 3 1
2 1 NULL NULL
3 1 NULL NULL
4 2 NULL NULL
So basically in the first query you are returning a limited number of rows from your table, whereas in the second you return all rows, but only join to some of them.
If the t.ID = '1' condition is in the WHERE clause the t.ID='1' condition only has to be evaluated for the number of rows in t. If the t.ID='1' condition is put into the ON clause for the join it must be evaluated for all rows in t2. If there are a lot of rows in t2 this can significantly increase the run time of the query.
You shouldn't include t.ID = '1' in JOIN ON condition since it's not the joined table. condition on the table in FROM part should stay in WHERE clause; whereas condition belongs to joined table should be moved to join on clause so to get a proper outer join effect rather a inner join effect.
You don't need an OUTER JOIN. The reason is simple, your are joining the same table on the same column - there can't be a non-match!
The query to use is therefore
Select *
FROM T
INNER JOIN T t2
ON T.MasterID = t2.MasterID
Where t.ID = 1
I have 2 tables with the same structure.
FIELD 1 INT
FIELD 2 VARCHAR(32) -- is a MD5 Hash
The query has to get matching FIELD 1 pairs from for records that have the exact combination of values for FIELD 2 in both TABLE 1 and TABLE 2.
These tables are pretty large ( 1 million records between the two ) but are deduced down to an ID and a Hash.
Example data:
TABLE 1
1 A
1 B
2 A
2 D
2 E
3 G
3 H
4 E
4 D
4 C
5 E
5 D
TABLE 2
8 A
8 B
9 E
9 D
9 C
10 F
11 G
11 H
12 B
12 D
13 A
13 B
14 E
14 A
The results of the query should be
8 1
9 4
11 3
13 1
I have tried creating a concatenated string of FIELD 2 using a correlated sub-query and FOR XML PATH string trick I read on here but that is very slow.
You can try following query also -
SELECT t_2.Field_1, t_1.Field_1 --1
FROM table_1 t_1, table_2 t_2 --2
WHERE t_1.Field_2 = t_2.Field_2 --3
GROUP BY t_1.Field_1, t_2.Field_1 --4
HAVING COUNT(*) = (SELECT COUNT(*) --5
FROM Table_1 t_1_1 --6
WHERE t_1_1.Field_1 = t_1.Field_1) --7
AND COUNT(*) = (SELECT COUNT(*) --8
FROM Table_2 t_2_1 --9
WHERE t_2_1.Field_1 =t_2.Field_1) --10
Edit
First the requested set of result is the combination of Field1 from both the tables where respective Field2 is exactly same.
so for that you can use one method which I have posted above.
Here
query will take the data from both the table based on field2 values (from line 1 to line 3)
then it will group the data based on field1 from table1 and field1 from table2 (line 4)
till this step you will get the result having field1 from table1 and field2 from table2 where it exists (at least one) matching based on field2 from tables for respective field1 values.
after this you just need to filter the result for correct (exactly same values for field2 values for respective field1 column value). so that you can make condition on row count.
here my assumption is that you don't have multiple values for field1 and field2 combination in either tables
means following rows will not be present -
1 b
1 b
In any of the tables.
if so, the rows count got for table1 and table2 for same field2 values should be match with the rows present in table1 for field1 and same rows only should present in tables2 for field2 value.
for this condition query has condition on count(*) in having clause (from line 5 to line 10).
Let me try to explain this version of the query:
select t1.field1 as t1field1, t2.field1 as t2field1
from (select t1.*,
count(*) over (partition by field1) as NumField2
from table1 t1
) t1 full outer join
(select t2.*,
count(*) over (partition by field1) as NumField2
from table2 t2
) t2
on t1.field2 = t2.field2
where t1.NumField2 = t2.NumField2
group by t1.Field1, t2.Field1
having count(t1.field2) = max(t1.NumField2) and
count(t2.field2) = max(t2.NumField2)
(which is here at SQLFiddle).
The idea is to compare the following counts for each pair of field1 values.
The number of field2 values on each.
The number of field2 values that they share.
All of these have to be equal.
Each subquery counts the number of values of field2 on each field1 value. For the first rows of your data, this produces:
1 A 2
1 B 2
2 A 3
2 D 3
2 E 3
. . .
And for the second table
8 A 2
8 B 2
9 E 3
9 D 3
9 C 3
Next, the full outer join is applied, requiring a match on both the count and the field2 value. This multiplies the data, producing rows such as:
1 A 2 8 A 2
1 B 2 8 B 2
2 A 3 NULL NULL NULL
2 D 3 9 D 3
2 E 3 9 E 3
NULL NULL NULL 9 C 3
And so on for all the possible combinations. Note that the NULLs appear due to the full outer join.
Note that when you have a pair, such as 1 and 8 that match, there are no rows with NULL values. When you have a pair with the same counts but they don't match, then you have NULL values. When you have a pair with different counts, they are filtered out by the where clause.
The filtering aggregation step applies these rules to get pairs that meet the first condition but not the second.
The having essentially removes any pair that has NULL values. When you count() a column, NULL values are not included. In that case, the count() on the column is fewer than the number of values expected (NumField2).