SQL Joins based on two tables - sql

I would like to combine two tables and obtain total# of the name by count() and group by functions.
Table_1 is shown below as;
name branch sports player no
---- ----- ------ --------
Mike 120 basketball 15
David 110 soccer 18
Table_2 is shown below as;
jersey color player no height
---------- --------- ------
Blue 15 182
Green 18 174
I tried to combine two tables by inner joins and count them based on the name such as;
SELECT name, branch, sports,
FROM TABLE_1
INNER JOIN TABLE_2
ON
TABLE_1.player no = TABLE_2.player no
COUNT(name) AS TOTAL
GROUP BY name, branch, sports, jersey color, player no, height
output should be
name branch player no jersey color height
---- ------ ------- -------- ----
Mike 120 15 Blue 182
David 110 18 Green 174
Mike 120 15 Blue 182
Mike 120 15 Blue 182
David 110 18 Green 174
After count(name)
name branch player no jersey color height Total
---- ------ ------- -------- ---- -----
Mike 120 15 Blue 182 3
David 110 18 Green 174 2
I have been pondering why I can not make this works?

You are essentially trying to combine the results one after the other, not side by side. This calls for a union [all], not a join:
SELECT name, COUNT(*)
FROM (SELECT name FROM table1
UNION ALL
SELECT name FROM table2) t
GROUP BY name

Related

ORACLE DB query - maximum stipend in faculty

So, i have an task in uni to get max stipend in each faculty from a table with stipends.
Faculty table is:
ID_FACULTY FACULTY_NAME DEAN TELEPHON
---------- ------------------------------ -------------------- --------
10 Informacijas tehnologiju Vitols 63023095
11 Lauksaimniecibas Gaile 63022584
12 Tehniska Dukulis 53020762
13 Partikas tehnologijas Sabovics 63021075
Money table is:
ID_PAYOUT STUDENT_ID PAYOUT_DA STIPEND COMPENSATION
---------- ---------- --------- ---------- ------------
100 1 24-SEP-20 45.25 15
101 7 20-SEP-20 149.99 0
102 3 18-SEP-20 100 0
103 17 02-SEP-20 90.85 20
104 9 03-SEP-20 85 20
105 19 09-SEP-20 70.75 0
106 25 15-SEP-20 55 15
107 17 17-SEP-20 105.54 0
108 15 22-SEP-20 94 0
109 27 28-SEP-20 100 20
And the student table is:
ID_STUDENT SURNAME NAME COURSE_YEAR FACULTY_ID BIRTHDATE
---------- ------------------------- -------------------- ----------- ---------- ---------
1 Lapa Juris 4 13 27-SEP-96
3 Vilkauss Fredis 2 10 17-MAY-99
5 Karlsone Rasa 1 11 13-MAR-00
7 Grozitis Guntars 3 12 16-APR-97
9 Sonciks Jurgis 2 10 17-MAR-99
11 Berzajs Olafs 3 10 14-FEB-97
13 Vike Ilvija 2 13 14-MAY-99
15 Baure Inga 3 11 12-APR-97
17 Viskers Zigmunds 2 13 15-AUG-99
19 Talmanis Harijs 3 13 15-JUL-97
21 Livmanis Indulis 1 10 19-JAN-00
23 Shaveja Uva 2 13 18-FEB-98
25 Lacis Guntis 4 10 17-SEP-96
27 Liepa Guna 4 11 18-AUG-96
29 Klava Juris 2 10 19-MAY-98
I have tried many variations of queries, i think that I even tried all the possible combinations of joins, but i cannot achieve the neccessary result.
One of my queries looked like this:
SQL> SELECT ROW_NUMBER() OVER (ORDER BY surname) "Nr.",
f.faculty_name,
s.surname,
s.name,
MAX(m.stipend)
FROM faculty f, student s INNER JOIN money m ON s.id_student = m.student_id
WHERE s.faculty_id = f.id_faculty
GROUP BY f.faculty_name, s.surname, s.name
ORDER BY s.surname;
Which returned me the following result:
Nr. FACULTY_NAME SURNAME NAME MAX(M.STIPEND)
---------- ------------------------------ ------------------------- -------------------- --------------
1 Lauksaimniecibas Baure Inga 94
2 Tehniska Grozitis Guntars 149.99
3 Informacijas tehnologiju Lacis Guntis 55
4 Partikas tehnologijas Lapa Juris 45.25
5 Lauksaimniecibas Liepa Guna 100
6 Informacijas tehnologiju Sonciks Jurgis 85
7 Partikas tehnologijas Talmanis Harijs 70.75
8 Informacijas tehnologiju Vilkauss Fredis 100
9 Partikas tehnologijas Viskers Zigmunds 105.54
9 rows selected.
So the goal of this task is to retrieve the maximum amount of stipend granted to a student in a certain faculty.
Can someone please tell what am I doing wrong here?
Just max amount per faculty:
SELECT
f.faculty_name,
MAX(m.stipend)
FROM
faculty f
INNER JOIN student s ON s.faculty_id = f.id_faculty
INNER JOIN money m ON s.id_student = m.student_id
GROUP BY f.faculty_name
Max amount and all other details too:
SELECT * FROM
(
SELECT
ROW_NUMBER() OVER (PARTITION BY f.faculty_name ORDER BY m.stipend desc) rn,
f.*,
s.*,
m.*
FROM
faculty f
INNER JOIN student s ON s.faculty_id = f.id_faculty
INNER JOIN money m ON s.id_student = m.student_id
) x
WHERE x.rn = 1
Points of note:
Do not use old style joins; if you ever write one table_name, other_table_name in a FROM block, you're using old style joins. Don't do it; they became bad news about 30 years ago
When you have a max-n-per-group, you specify how finely detailed the group is. If you GROUP BY s.first_name, s.last_name, f.faculty_name then your groups are "every unique combination of firstname/lastname/faculty, so the only way you'll get multiple items in your group is if there are two John Smiths in Mathematics. If the group is to be the whole of mathematics, then the faculty name (and anything else that is uniquely related 1:1 to it, like the faculty ID) is all that you can put in your group. Anything not in a group must be in an aggregation, like MAX
When you want other details too, you either group and max the data and then join this groupmaxed data back to the original data to use it as a filter, or you use an approach like here where you use a row_number or rank, with a partition (which is like an autojoined grouped summary). There is no group here; the row numbering acts like a group because it restarts from 1 every different faculty and proceeds incrementally as stipend decreses. This means that the highest stipend is always in row number 1.
Unlike using a groupmax that you join back to get the detail, the row_number route does not produce duplicate rows with tied-for-highest stipends

how to get the unique max data

I have below table
userid comp_dd coursecode qualification course_id course passyear totalmarks func stream
----------- ----------- ----------- --------------- ----------- -------------------------------------------------- ----------- -----------------
60 26 1 High School 15 Class 10 26 67 2 All Subject
60 26 2 Senior Secondry 15 Class 12 26 85 2 Commerce
60 2010 3 Graduates 4 B.Tech/B.E 2010 54 1 IT/Computers
60 2013 4 Post Graduates 9 M.com 2013 98.5 2 Commerce
i wanted to get the unique record of max coursecode, the output should be
userid comp_dd coursecode qualification course_id course passyear totalmarks func stream
----------- ----------- ----------- --------------- ----------- -------------------------------------------------- ----------- -----------------
60 2013 4 Post Graduates 9 M.com 2013 98.5 2 Commerce
There will be many records of the different userids
I think you want:
select t.*
from t
where t.coursecode = (select max(t2.coursecode)
from t t2
where t2.userid = t.userid
);
You can also do this with window functions, but the correlated subquery is often faster with the right index, which would be on (userid, coursecode).
Sort the table by coursecode descending and get the 1st row:
select top 1 *
from tablename
order by coursecode desc
This will work only if there are no duplicates in the column coursecode since it will fetch only 1 row, but I guess this is the case because you say:
i wanted to get the unique record of max coursecode

how to write this query in sql-server?

This is my table structure in sql-server:
id Marks
---------- -----------
AAA 50
KKK 87
KKK 89
BBB 48
CCC 54
AAA 52
DDD 55
BBB 60
XXX 99
This is the desired output:
Name attempts Max Mark
------- ---------------- ------------
AAA 2 52
kkk 2 89
BBB 2 60
CCC 1 54
DDD 1 55
XXX 1 99
I've tried this but it seems incorrect:
SELECT
name,
count(*) as attempts,
max(marks)
FROM table_name
GROUP BY name, attempts, max_marks
Try this one:
SELECT
id AS Name,
count(id) AS attempts,
max(Marks) AS Max_Mark
FROM table_name
GROUP BY id
You were on the right track just added too much to grouping field,
SELECT id AS name
,COUNT(*) AS Attempts
,MAX(marks) as MaxMarks
FROM table_name
GROUP BY id
If your column is already part of aggregate function such as MAX or COUNT it does not need to be included in GROUP BY clause

How does select query works?

I having trouble with this query
it is executing quit well but I cannot make out
how is this select statement working.
Any help or explanation on this problem will be appreciated ..
thank you
these are my tables and query
here am looking for the employee who lives in same city as the the company for which they work
Table:-emp
eid name street city
----------- ---------------- ------------- ------------
1 yeman asd vasai
2 aksh adssd mumbai
3 chintan ghfgh mumbai
4 samual ghfdgh bandra
5 ddlj fghfgh andheri
6 jack fghnfg Bandra
7 bridge gfhfgh vasai
8 rahim ghfgh mumbai
9 chirag fghfghfg bandra
10 mistry hhhty bandra
11 ravi tytey andheri
Table:- company
cid companyname city
----------- ------------------- ------------
1 Vasai Industries vasai
2 Mumbai Pharmacy mumbai
3 bandra loft bandra
4 andheri tactics andheri
Table:= works
eid cid salary
----------- ----------- -----------
1 1 200
2 3 4831
3 4 4457
4 2 20001
5 1 32221
6 2 224
7 3 784
8 1 336
9 3 2489
10 2 4789
11 1 22541
Query
select * from emp
where eid
IN (select eid from works
where cid=(select cid from company
where city=emp.city))
why not use this query with joins and its easy to understand then a bunch of subqueries.
select * from emp
inner join works on works.eid = emp.eid
inner join company on company.city=emp.city
Explanation:
1.select cid from company where city=emp.city
Here you are getting city id regarding cities which are same in emp and company
2.
select eid from works
where cid=(select cid from company
where city=emp.city)
Here you getting collection of id's from works table which cid is same in emp and company
3.
select * from emp
where eid
IN (select eid from works
where cid=(select cid from company
where city=emp.city))
here you are getting all records based on emp id's whose cities are same in emp and city

How to bring together multiple delta tables?

I have a table with IDs and primary information. I also have two delta tables keyed on ID and date of change. I need to build a view that merges these three tables together indicating all changes over time.
Main Table:
ID Name
-- ------------------
1 Bob Jones
2 Dave Smith
First Attribute Table:
ID Date Attr1
-- ---------- -----
1 01/01/2013 25
1 02/15/2013 33
1 02/17/2013 47
1 03/02/2013 58
2 02/01/2013 1
...
Second Attribute Table
ID Date Attr2
-- ---------- -----
1 01/01/2013 ABC
1 01/05/2013 DEF
1 01/15/2013 RST
1 02/10/2013 XYZ
1 02/15/2013 Foo
1 03/05/2013 Blah
2 02/01/2013 Two
...
Based on that data, for Bob Jones, I need the view to return the following:
ID Name Date Attr1 Attr2
-- ----------- ---------- ----- -----
1 Bob Jones 01/01/2013 25 ABC
1 Bob Jones 01/05/2013 25 DEF
1 Bob Jones 01/15/2013 25 RST
1 Bob Jones 02/10/2013 25 XYZ
1 Bob Jones 02/15/2013 33 Foo
1 Bob Jones 02/17/2013 47 Foo
1 Bob Jones 03/02/2013 58 Foo
1 Bob Jones 03/05/2013 58 Blah
I tried outer joining the attribute tables to get all change values ordered by date and then used an outer join on the entire query with itself to get "prior" records:
with qry as (
select
rownum = ROW_NUMBER() OVER (ORDER BY m.ID, a.DATE),
m.ID,
m.Name,
a.DATE,
a.Attr1,
a.Attr2
from Main m
inner join (
select
COALESCE(a1.ID, a2.ID) as ID,
COALESCE(a1.LOAD_DATE, a2.LOAD_DATE) as LOAD_DATE,
a1.Attr1,
a2.Attr2
from Attributes1 a1
full outer join Attributes2 a2
on (a1.ID = a2.ID and a1.DATE = a2.DATE)
) a on (a.ID = m.ID)
)
select
COALESCE(qry.ID, prev.ID) as ID,
COALESCE(qry.Name, prev.Name) as Name,
COALESCE(qry.DATE, prev.DATE) as DATE,
COALESCE(qry.Attr1, prev.Attr1) as Attr1,
COALESCE(qry.Attr2, prev.Attr2) as Attr2,
from qry
left join qry prev
on (prev.rownum = qry.rownum - 1)
order by ID, DATE
However, that doesn't work when one attribute table changes quicker than the other because the attributes that didn't change are null in the results of the attribute table join and if two nulls show up back-to-back, the coalesce will return a null when I need the last non-null value that was in that column.
Can this even be done in a view in SQL Server 2012?