SQL query : Inner join with distinct values - sql

I have two tables :
Table 1
ID | Name
12 User1
77 CostCenter1
78 CostCenter2
79 CostCenter3
14 User2
Table 2
UserID | AssignedCostCenter
12 77
12 78
12 79
14 78
1st table collects identities (users, cost centers).
2nd table represents users and their allowed CostCenters.
I would like to achieve the following:
query should returns a single column which have a list of (unique) users who have assigned more then 1 cost center (two and more).
I started with join two tables by:
Select Table 1.Name
from Table 1
inner join Table 1.ID = Table 2.UserID
The result is:
User1
User1
User1
User2

You are getting "user1" and "user2" because of inner join based upon Ids.
To get the list of users who have been assigned more than 1 cost center (two and more), modify your query as:
SELECT Table 1.Name
FROM Table 1
INNER JOIN Table 2 ON Table 1.ID = Table 2.UserID
GROUP BY Table 1.Name
HAVING count(Table 1.name) > 1

Using group by on the userid in table2 allows use of a having clause which filters out those who only have 1 cost centre, then the inner join to that result will list the just the names of those who have more than one cost centre.
SELECT
Table1.Name
FROM Table1
INNER JOIN (
SELECT
UserID
FROM Table2
GROUP BY
UserID
HAVING COUNT(UserID) > 1
) AS t2 ON Table1.ID = t2.UserID

Your question is unclear on whether table 2 can have duplicates. So, it might be safer to approach this query as:
SELECT t1.Name
FROM Table1 t1 JOIN
Table2 t2
ON t1.ID = t2.UserID
GROUP BY t1.Name
HAVING MIN(t2.AssignedCostCenter) <> MAX(t2. AssignedCostCenter);

Related

Merging to table from 2 joined tables

For example I am having two tables with id,age,status and height. And there is a table RESULT which I need to merge to.
Table 1
*id age status*
1 15 1
2 16 1
3 17 0
Table 2
*id height*
1 160
2 170
3 180
And Result table is:
Result table
*id age height*
1 15 160
I need to insert into Result table id,height,age from Table 1 join Table 2 on ID ,where status is 1.
How can I write something like
Merge into Result
USING(Select ... from Table1
join Table2 on Table1.id=Table2.id where status=1)
When Not Matched THEN
Insert into Result VALUES(Table1.id,age,height)
I need to get
RESULT
*id age height*
1 15 160
2 16 170
So how can I implement that merge which will find user with id=2 in Result
Table and Insert and will not Insert user with id=1 because it is already in table?
Try this:
MERGE INTO RESULT R USING (
SELECT
T1.ID,
T1.AGE,
T1.STATUS,
T2.HEIGHT
FROM
TABLE1 T1
JOIN TABLE2 T2 ON T1.ID = T2.ID
WHERE
STATUS = 1
) DATAA
ON ( R.ID = DATAA.ID )
WHEN NOT MATCHED
THEN INSERT (
ID,
AGE,
HEIGHT )
VALUES (
DATAA.ID,
DATAA.AGE,
DATAA.HEIGHT )
Cheers!!
Below is the sql query in need to run whole query together
insert into result
Select t1.Id, t1.Age, t2.Height from Table1 t1 inner join Table2 t2 on t1.Id=t2.Id where t1.status=1

How to left join on two tables on just unique ids

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.

Oracle SQL - Joining tables to include one column to the other (vice versa)

These are my sample tables, columns and records...
Table: tbl1
-----------------------
Columns: ID | DEPT | WK | MANHRS
Records: 01 A 1 8
02 A 2 2
Table: tbl2
--------------------------------
Columns: ID | DEPT | WK | WAGES
Records: 01 A 1 3
02 A 2 5
Scenario:
I want to have a result where two tables are joined and MANHRS and WAGES columns are both together in the result set.
Expected output of the result table:
Columns: ID | DEPT | WK | MANHRS | WAGES
01 A 1 8 3
02 A 2 2 5
I tried UNION but didn't get my expected result. :(
How to do this?
The proper way to write the query is:
SELECT t1.*, t2.WAGES
FROM tbl1 t1 JOIN
tbl2 t2
ON t1.DEPT = t2.DEPT and t1.WK = t2.WK;
Notes:
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
I'm not sure if ID should be in the JOIN conditions.
If you want all rows in both tables, but some might be missing, then use FULL JOIN.
You can write the query with the USING clause:
SELECT ID, DEPT, WK, t1.MANHRS, t2.WAGES
FROM tbl1 t1 JOIN
tbl2 t2
USING (ID, DEPT, WK);
This is particularly useful if you are using a FULL JOIN.
Assuming that you should join by DEPT and WK:
SELECT t1.*, t2.WAGES
FROM tbl1 t1, tbl2 t2
where t1.DEPT = t2.DEPT and t1.WK = t2.WK

Why is my SQL request much slower when the condition is in the join?

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

fusion 2 tables with inner join

in my database i have 2 tables.
table1
i have ID and NAMES
table2
i have ID, IDASSOCIATION, QUANTITY
so
i have 2 names in table1:
john and tom
and in table2 i have 3 lignes
john, 1
tom, 1
john, 1
nombre one is the quantity
in my result i want get
john = 2
and tom = 1
so i do this:
sql = "SELECT t1.*, t2.IDASSOCIATION, (SELECT SUM(t2.id_qte) FROM associationdepotarticle t2 WHERE t1.fusiontable = t2.fusiontable GROUP BY t2.IDASSOCIATION) as id_qte FROM articletable t1, associationdepotarticle t2";
but i not get this:
john = 2
tom = 1
why ? what i will do, i need correction please
You can just join the tables together and use sum:
select t1.name, sum(t2.quantity)
from table1 t1
join table2 t2 on t1.id = t2.idassociation
group by t1.name
It's not completely clear from your sample data what to join on, but I assume it's the idassociation field. If you want to return those names in table1 which aren't in table2, then use an outer join.