Given two tables (the rows in each table are distinct):
1) x | y z 2) x | y z
------- --- ------- ---
1 | a a 1 | a a
1 | b b 1 | b b
2 | a 1 | c
2 | b 2 | a
2 | c 2 | b
2 | c
Is there a way to select the values in the x column of the first table for which the subset of values in the y column, for that x, matches exactly the values in the z column of the second table?
In case 1), expected result is 1. If c is added to the second table then the expected result is 2.
In case 2), expected result is no record since neither of the subsets in the first table matches the subset in the second table. If c is added to the second table then the expected result is 1, 2.
I've tried using except and intersect to compare subsets of first table with the second table, which works fine, but it takes too long on the intersect part and I can't figure out why (the first table has about 10.000 records and the second has around 10).
EDIT: I've updated the question to provide an extra scenario.
SELECT
table1.x
FROM
table1
INNER JOIN
table2
ON table1.y = table2.z
GROUP BY
table1.x
HAVING
COUNT(*) = (SELECT COUNT(*) FROM table2 AS lookup)
AND COUNT(*) = (SELECT COUNT(*) FROM table1 AS lookup WHERE x = table1.x)
One of these will do
select
t1.x
from
table1 as t1 inner join table2 as t2 on t1.x=t2.x
group by t1.x
having count(distinct t1.x)=count(distinct t2.x)
select
t1.x
from
table1 as t1 inner join table2 as t2 on t1.x=t2.x
group by t1.x
having count(distinct t1.x)=(select count(distinct x) from table2)
Related
Tabel 1 :
ID1
ID2
ID3
MainID
Location
1
A
X
1AX
VIC
2
B
Y
2BY
SYD
3
C
W
3CW
TAS
4
D
Z
4DZ
TAS
Tabel 2 :
SALESID
QTY
AMT
DIFF
1AX
1
100
2
2BY
2
0
3
3CW
3
5
4DZ
3
12
2
Ignore other fields, I need to delete all raws in Tabel 1 where AMT in Tabel 2 has zero or no value for the SALESID.
For example, after the query, only raws containing 1AX & 4DZ should be remain in Tabel 1.
this can be done by subquery
get all MainID from table2 where amt is 0 or null
delete all rows that equal to previous fetched MainID
delete from table1 where MainID in (
select SALESID from table2 where AMT <=0 or AMT is null
)
You can use exists:
delete from table1
where exists (select 1
from table2 t2
where table1.mainid = t2.salesid and
(t2.amt = 0 or t2.amt is null)
);
Thinking an INNER JOIN would be much faster on larger data sets. Something like this:
DELETE
T1
FROM
Table1 T1
INNER JOIN
Table2 T2 ON T2.SalesID = T1.MainID
WHERE
IsNull(T2.Amt,0) = 0
I have two tables
Table 1:
color_id | label
---------|------
2 | 0
3 | 0
2 | 0
1 | 0
4 | 1
4 | 1
5 | 0
Table 2:
color_id
--------
2
1
4
I want a query that just gives me results for color_ids that are present in Table 2
So, I wrote:
SELECT *
FROM table1
LEFT JOIN table2
ON table1.color_id = table2.color_id
WHERE table2.color_id IS NOT NULL
however, the above gives duplicates as well. Meaning I get
2 | 0
2 | 0
1 | 0
4 | 1
4 | 1
I don't want the duplicates in the results. I just want unique items.
I want a query that just gives me results for color_ids that are present in Table 2
So, you shouldn't use LEFT JOIN in this case:
SELECT DISTINCT a.color_id, a.label
FROM table_1 a JOIN table_2 b
ON a.color_id = b.color_id
When you add the keyword Left (or Right or full) to a join specifier, you make the join an outer join. This means that you get all the rows from one side of the join, and only those rows from the other side that match. If you only want the rows from table_1 where the color_id is in table_2, then you want an inner join, specified by writing inner join or just writing join, without a left, right or full.
to eliminate duplicates, add the keyword distinct to the select clause...
Select distinct color_id, label
From table1 t1
join table2 t2
on t2.color_id = t1.color_id
Try the below query
SELECT DISTINCT color_id
FROM table_1 T1
WHERE EXISTS (SELECT 1 FROM table_2 T2 where T1.color_id = T2.color_id)
Use an inner join and a distinct clause:
SELECT DISTINCT table1.color_id, table1.label
FROM table1
INNER JOIN table2
ON table1.color_id = table2.color_id
What you are looking for is an INNER JOIN combined with a
SELECT distinct table1.color_id, tabl1.label
FROM table1
INNER JOIN table2 ON table1.color_id = table2.color_id
This eliminates any item in table1 not present in table 2 and duplicated rows.
the reason of that is you used Left Join, which will keep all obs in table1.
Try this:
SELECT table1.* FROM table1 Inner JOIN table2 ON table1.color_id = table2.color_id
this should works as actually all table2 obs are in table1. To be more serious, if table2 has obs that are not in table1 and you do want to keep them, replace inner join with right join.
I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D
Lets say I have following tables:
Table1
ID Number
1 2
2 34
3 1 <---- Input (ID = 3) ==> (Number = 1)
4 6
5 5
*6* 7 <---- Want to find (Number = 6) because match in Table2
7 22
and Table2
Number Code Att1 Att2 Att3
1 1 1 <-----|
1 2 1 2 <-----|
6 2 f 2 |
6 3 4 3 2 |
2 4 6 |---Match
22 5 2 2 2 |
5 2 h 3 b |
7 1 1 <-----|
7 2 1 2 <-----|
7 h 5 r
So here is my Problem:
I want the IDs from Table1 that have all Code and Attributes from Table2 that a given (variable) input ID has. At the end I want to create a stored procedure/function that gives me all IDs meeting that condition.
As an Example:
Input-ID: 3. Would return ID 6 because Number 7 (mapped from ID 6 in Table1) has the rows Number 1 (mapped from ID 3 in Table1) has. It has more but that doesn't matter, its just important it has all rows the input one has.
(I can't find a solution to comparing a set of rows to another set of rows that is not known before.)
Thanks for any help!
Edit:
To make it more understandible, here what I want in words step-by-step.
Map input ID to Number in Table1
Get All Rows from Table2 having Number from Step 1
Get all Number that have the same (can have more) Rows as from Step 2
Get IDs for that Numbers (and return them)
Try something like this. Haven't tested it, but basically you inner join on all of the attributes that need to match. The HAVING clause is a crude check to make sure that it matched all the rows. Edit: Forgot to add the input ID WHERE clause.
SELECT t1b.ID FROM
Table1 t1a
INNER JOIN Table2 t2a ON t1a.Number = t2a.Number
INNER JOIN Table2 t2b ON t2a.Number <> t2b.Number AND t2a.Code = t2b.CODE AND t2a.Att1 = t2b.Att1 AND t2a.Att2 = t2b.Att2 AND t2a.Att3 = t2b.Att3
INNER JOIN Table1 t1b ON t1b.Number = t2b.Number
WHERE t1a.ID = 3
GROUP BY t1b.ID
HAVING COUNT(*) = (SELECT COUNT(*) FROM Table1 WHERE ID = t1a.ID)
select t11.ID as Id_To_Find,t12.ID as Id_Found
from Table1 t11
join (
select t21.Number as Found,t22.Number as ToFind from Table2 t21
left join Table2 t22 on t21.Code = t22.Code
and t21.Att1 = t22.Att1
and t21.Att2 = t22.Att2
and t21.Att3 = t22.Att3
and t21.Number <> t22.Number
group by t21.Number,t22.Number
having COUNT(*) = (select COUNT(*) from Table2 where Number = t22.Number))
as FindMatches
on t11.Number = FindMatches.ToFind
join Table1 t12 on t12.Number = FindMatches.Found
Kind of hard to understand what you're trying to acheive. As i understood from your example, you want to match the Number for the input ID in Table1 with any column (correct?) in Table2.
With input ID=3, the SELECT will return Number=7. In the IN (...)-condition, you can specify whichever columns in Table2 you want to match to Table1.Number.
DECLARE #Input INT = 3 -- Your input
SELECT DISTINCT t1.Number
FROM Table1 t
INNER JOIN Table2 t2 ON t.Number IN (t2.Number, t2.Code, t2.Att1, t2.Att2, t2.Att3)
INNER JOIN Table1 t1 ON t2.Number = t1.Number AND t.ID <> t1.ID
WHERE t.ID = #Input
I have the following tables in a Hive database:
table1:
id t X
1 1 a
1 4 a
2 5 a
3 10 a
table2:
id t Y
1 3 b
2 6 b
2 8 b
3 15 b
And I would like to merge them to have a table like:
id t Z
1 1 a
1 3 b
1 4 a
2 5 a
2 6 b
2 8 b
3 10 a
3 15 b
Basically what I want to do is :
a join on the column id (that part is easy)
merge the columns table1.t and table2.t into a new column t
have the variable Z that is equal to table1.X if the corresponding t comes from table1.t, and table2.Y if it comes from table2.t
order the table by id and then by t (that shouldn't be too hard)
I have no idea on how to do the parts 2 and 3. I tried with an outer join on
table1.id = table2.id and table1.t = table2.t, but it doesn't merge the two columns t.
Any pointer would be appreciated. Thanks!
CREATE TABLE table3 as SELECT * FROM (SELECT id,t,X as Z FROM t3_1 UNION ALL SELECT id,t,Y as Z FROM t3_2) u1 order by id,t;
Although not always required, using a subquery for the union'd queries help to organize, plus you can then reference the fields from the union (e.g. u1.id ) in other parts of the query.
You'll need the alias on the 3rd column to make the schemas match. If the source table name was not already a column, you could do something like this:
select * from (select id,t,'a' from t3_1 UNION ALL select id,t,'b' from t3_2) u1;
Try this one. It will insert in table 3, all the values from the other 2 tables
INSERT INTO table3 ( t, Z )
SELECT t, X
FROM table1
UNION ALL
SELECT t, Y
FROM table2