I have two hive tables as follows:
names
id name
1 mark
2 smith
3 john
4 robin
Names
id name
3 john
4 smith
5 tailor
6 will
I want to join the tables so that the resultant set should contain the non overlapping values of both first and second tables.
id name
1 mark
2 smith
5 tailor
6 will
How can I do this?
Try with Full outer join and then filter only the null records from the resultant set then apply coalesce function to get non null value for the columns.
Example:
select coalesce(tmp.id,tmp1.id)id,
coalesce(tmp.name,tmp1.name)name
from table1 full outer join table2
on table1.id = table2.id
where table1.id is null or table2.id is null;
Result:
+---+------+
| id| name|
+---+------+
| 1| mark|
| 6| will|
| 5|tailor|
| 2| smith|
+---+------+
Related
I'm learning sql and foreign keys.
I'm now stuck with a task which I don't know how to proceed.
Description:
The task is to collect the name_id, name, lastname of table1 and game_id and game from table2 (see the tables bellow).
Problem:
I would use the name_id to collect the data from both tables using "WHERE table1.name_id = table2.name_id" but in that process name_id 3 will not appear because it has no connection to table2.
Code will appear like this missing name_id 3.
1 | name1| lastname1
2 | name2| lastname2
Optimal outcome
1 | name1| lastname1| 1| game1
2 | name2| lastname2| 2| game2
3 | name3| lastname3
Question:
How do I collect this value? Is it a logic problem or should I use JOIN to put them together?
table1
name_id | name | lastname
1 | name1| lastname1
2 | name2| lastname2
3 | name3| lastname3
table2
game_id | game | name_id
1 | game1| 1
2 | game2| 2
Thank you!
You want a left join:
select *
from table1 t1 left join
table2 t2
using (name_id);
I'm trying to display left over records after matching one-to-one rows. How do I display extra/left over records after joining two tables?
Suppose I have two tables, A and B. They both display the the same transactions at the end of the day. However, Table A has more detail about the records but is late in getting updated. Table B, on the other hand, has limited information about transactions but is updated several hours before Table A.
I need a query that can return which records have yet to appear in Table A from Table B.
TABLE A
+-------+-----+---------+----------+---------------------------+
| NAME | ID | AMOUNT | TYPE | PROCESSED TIMESTAMP |
+-------+-----+---------+----------+---------------------------+
| ABC | 123 | -420.07 | PURCHASE | 2018-09-06-08.26.32.000000|
| ABC | 123 | 420.07 | REFUND | 2018-09-06-07.12.18.000000|
| BBC | 456 | -5.00 | PURCHASE | 2018-09-06-10.25.13.000000|
+-------+-----+---------+----------+---------------------------+
TABLE B
+----+----------+---------------------------+
| ID | AMOUNT | RECEIVED TIMESTAMP |
+----+----------+---------------------------+
|123 | -420.07 | 2018-09-05-09.26.15.000000|
|123 | 420.07 | 2018-09-05-08.12.03.000000|
|123 | -420.07 | 2018-09-05-08.40.00.000000|
|456 | -5.00 | 2018-09-05-08.45.00.000000|
+----+----------+---------------------------+
QUERY RESULTS
+----+----------+
| ID | AMOUNT |
+----+----------+
|123 | -420.07 |
+----+----------+
I can manage to find all the records related to the ID that is "off balance" but I need only the specific records that are extra:
SELECT * FROM b
WHERE id
IN
(SELECT d.id AS id
FROM
(SELECT * FROM
(SELECT id, ROUND(SUM(amount),2) AS balance FROM a GROUP BY id) c
RIGHT JOIN
(SELECT id, ROUND(SUM(amount),2) AS balance FROM b GROUP BY id) d
ON c.id = d.id
WHERE c.balance <> d.balance))
Yields...
+----+----------+
| ID | AMOUNT |
+----+----------+
|123 | -420.07 |
|123 | 420.07 |
|123 | -420.07 |
+----+----------+
You need to read up more on joins . There are 3 basic joins which can make life much simpler.
INNER JOIN: First, this is not asked, but the query you have provided for finding off balance items is too complicated. It can be simplified by an inner join.
Inner join is a set operation which will basically get data from both tables (set) which match the condition.
select * from
(
(select id, sum(amount) from a group by id) group_A
INNER JOIN (select id, sum(amount) from b group by id) group_B
ON group_A.id = group_B.id
WHERE group_A.balance != group_B.balance
)
LEFT/RIGHT OUTER JOIN: Left outer join is an operation which will return all the data that is present in both sets and also the data that is in left set but not the right set. Right join is essential same operation on the right set. Important to notice that the extra records pulled here would be null for the side where they do not exist.
Since you want records which are present in table B but not in A, there are multiple ways of achieving this, one would be to get records present in both tables (inner join) and then get all the records in table B but not in the inner join done earlier. Using definition of group_A/group_B from the inner join example.
select id from b where id not in (
select id from group_A INNER JOIN group_B on group_A.id = group_B.id)
Or you can do a right outer join and then using the property of that fields fetched from table A would be coming as null, can filter out the required ID.
select group_B.id from group_A RIGHT OUTER JOIN group_B ON group_A.id = group_B.id
where group_A.id is null
Please use the primary keys on the joins to get the correct results as mentioned by user #ComputerVersteher
I think, you should add PK col.
I can't match data with table A and B, and can't seperate 2 rows at table B.
+----+----------+---------------------------+
| ID | AMOUNT | RECEIVED TIMESTAMP |
+----+----------+---------------------------+
|123 | -420.07 | 2018-09-05-09.26.15.000000|<-
|123 | 420.07 | 2018-09-05-08.12.03.000000|
|123 | -420.07 | 2018-09-05-08.40.00.000000|<-
|456 | -5.00 | 2018-09-05-08.45.00.000000|
+----+----------+---------------------------+
I add new col(deal_no) and made it.
https://www.db-fiddle.com/f/3GfZoQwGhBLf7YWf2RucBF/4
select tmp_B.deal_no, tmp_B.id, tmp_B.amount, tmp_A.deal_no
from tmp_B
left outer join tmp_A
on tmp_A.deal_no = tmp_B.deal_no
where tmp_A.deal_no is null
I am trying to figure out the best way to use a JOIN in MSSQL in order to do the following:
I have two tables. One table contains technician IDs and an example of one data set would be as follows:
+--------+---------+---------+---------+---------+
| tagid | techBid | techPid | techFid | techMid |
+--------+---------+---------+---------+---------+
| 1-1001 | 12 | 0 | 11 | 6 |
+--------+---------+---------+---------+---------+
I have another table that stores the names of these technicians:
+------+-----------+
| TTID | SHORTNAME |
+------+-----------+
| 11 | Steven |
| 12 | Mark |
| 6 | Pierce |
+------+-----------+
If the ID of a technician in the first table is 0, there is no technician of that type for that row (types are either B, P, F, or M).
I am trying to come up with a query that will give me a result that contains all of the data from table 1 along with the shortnames from table 2 IF there is a matching ID, so the result would look something like the following:
+--------+---------+---------+---------+---------+----------------+----------------+----------------+----------------+
| tagid | techBid | techPid | techFid | techMid | techBShortName | techPShortName | techFShortName | techMShortName |
+--------+---------+---------+---------+---------+----------------+----------------+----------------+----------------+
| 1-1001 | 12 | 0 | 11 | 6 | Mark | NULL | Steven | Pierce |
+--------+---------+---------+---------+---------+----------------+----------------+----------------+----------------+
I am trying to use a JOIN to do this, but I cannot figure out how to join on multiple columns multiple times to where it would look something like
Select table1.tagid, table1.techBid, table1.techPid, table1.techFid, table1.techMid, table2.shortname
FROM table1
INNER JOIN table2 on //Dont know what to put here
You need to use left joins like this:
Select table1.tagid, table1.techBid, table1.techPid, table1.techFid, table1.techMid,
t2b.shortname, t2p.shortname, t2f.shortname, t2m.shortname,
FROM table1
LEFT JOIN table2 t2b on table1.techBid = t2b.ttid
LEFT JOIN table2 t2p on table1.techPid = t2p.ttid
LEFT JOIN table2 t2f on table1.techFid = t2f.ttid
LEFT JOIN table2 t2m on table1.techMid = t2m.ttid
you just do mutiple left join
select tech.techPid, techPname.SHORTNAME
, tech.techFid, techFname.SHORTNAME
from tech
left join techName as techPname
on tech.techPid = techPname.TTID
left join techName as techFname
on tech.techFid = techFname.TTID
i am building a query for a table that has several columns:
name
date
about 10 columns with integer values
Now i want to return a table that returns one row for each unique element of the name column.
This row has three columns: name, date, and an average of the integer values columns.
The date is the most current date for this particular name element.
And the average value is the average of all integer values of this particular row.
SELECT name, Max(date), SUM(value1+value2+value3+value4...+value10)/10
FROM myTable
WHERE *join statements*
Group by name
The problem with this is, that due to the face that sum aggregates all the values of the columns, the computed value is not the average of this single row.
Adding the values to the group by statement is not possible because the result should be displayed only by one row per name.
Hope the problem is clear. Any Ideas? Thanks!
Edit:
Thank you for your reply Gordon Linoff! The formulation of my problem was not that clear, sorry for that.
Actually there can exist entries with same name and date. Therefore I need to aggregate these entries, in case it is the most current date of this particular name element.
To clarify, here a possible table:
|Name |Date |value1|value2|
|Name A | 14/09/24 | 1 | 2 |
|Name A | 14/09/24 | 2 | 1 |
|Name A | 14/09/24 | 9 | 9 |
|Name A | 14/09/22 | 4 | 3 |
|Name B | 14/09/23 | 3 | 5 |
|Name B | 14/09/22 | 2 | 4 |
|Name B | 14/09/21 | 4 | 2 |
|Name C | 14/09/23 | 5 | 1 |
The result shoud be:
|Name |Date |avg|
|Name A | 14/09/24 | 4 |
|Name B | 14/09/23 | 4 |
|Name C | 14/09/23 | 3 |
With your hint, I think I found the right query for this problem, where 2 is the number of values per row:
SELECT name, max(date), avg(value1+value2)/2
FROM myTable t
WHERE not exists (select 1
from myTable t2
where t2.name = t.name and t2.date > t.date
)
group by name
You don't actually want an aggregate. You want to choose the most recent row for each name. Here is a method that uses not exists:
SELECT name, date, (value1+value2+value3+value4...+value10)/10
FROM myTable t
WHERE not exists (select 1
from myTable t2
where t2.name = t.name and t2.date > t.date
);
i want to get the data of five table having a common id from one query can we do this ,
for example tbl_student,tbl_batch,tbl_section,tbl_level,tbl_faculty all have a common id
college_id
how can i get all the tables value with one query
if anybody can help me i would be greatful
If I understand you correctly that sounds like a join.
select * from tbl_student st
join tbl_batch ba on ba.college_id=st.college_id
join tbl_section se on se.college_id=st.college_id
join tbl_level le on le.college_id=st.college_id
join tbl_faculty fa on fa.college_id=st.college_id
This is most probably not exactly the way you want to get the data because the data model would not make much sense. Hopefully you get the idea though.
SELECT fields FROM table1
LEFT JOIN table2 ON table1.id = table2.id
LEFT JOIN table3 ON table1.id = table3.id
LEFT JOIN table4 ON table1.id = table4.id
You can do it, but it won't make a lot of sense.
Your SQL query returns a 2-D table with the same columns for each row. If some of your rows are students and some of them are faculties, then there will be a bunch of columns that make sense for students but don't make sense for faculties, and for a faculty row those columns should be null.
The SQL to do this for two tables is:
SELECT t_F.college_id AS college_id, t_F.f_1, t_F.f_2, NULL , NULL
FROM tbl_Faculty AS t_F
UNION
SELECT t_S.college_id AS college_id, NULL , NULL , t_S.s_1, t_S.s_2
FROM tbl_Student AS t_S
ORDER BY college_id
Then your results will look like:
college| Faculty field 1 | 2 | Student field 1 | 2
--------------------------------------------------------------
1 | abc | def | NULL | NULL
1 | abc | ghi | NULL | NULL
1 | NULL | NULL| asdoifjas | aosdifjasdf
1 | NULL | NULL| asdoifjas | aosdifjasdf
2 | abc321 | aaa | NULL | NULL
2 | abc456 | bbb | NULL | NULL
2 | NULL | NULL| afasdfafs | aosdifjasdf
2 | NULL | NULL| asdoifjas | aoffavsdfff
This doesn't make that much sense to me.