How to solve this using a subquery in a from clause? - sql

Display author, title, retail and retail price of all books whose retail price is the highest for the specific author.
I have the query below. I'm kinda confused how to do a subquery in a from clause.
select lname, fname, title, retail
from author natural join bookauthor
natural join books
where retail=(select max(retail)
from books);
Below is the data from the database that I'm using
FNAME LNAME TITLE RETAIL
---------- ---------- ------------------------------ ----------
SAM SMITH BODYBUILD IN 10 MINUTES A DAY 30.95
LISA PORTER BODYBUILD IN 10 MINUTES A DAY 30.95
JANICE JONES REVENGE OF MICKEY 22
TAMARA KZOCHSKY BUILDING A CAR WITH TOOTHPICKS 59.95
TINA PETERSON DATABASE IMPLEMENTATION 55.95
JUAN ADAMS DATABASE IMPLEMENTATION 55.95
JAMES AUSTIN DATABASE IMPLEMENTATION 55.95
JACK BAKER COOKING WITH MUSHROOMS 19.95
JAMES AUSTIN HOLY GRAIL OF ORACLE 75.95
LISA WHITE HANDCRANKED COMPUTERS 25
WILLIAM WHITE HANDCRANKED COMPUTERS 25
JANICE JONES E-BUSINESS THE EASY WAY 54.5
ROBERT ROBINSON PAINLESS CHILD-REARING 89.95
OSCAR FIELDS PAINLESS CHILD-REARING 89.95
JACK BAKER PAINLESS CHILD-REARING 89.95
SAM SMITH THE WOK WAY TO COOK 28.75
ROBERT ROBINSON BIG BEAR AND LITTLE DOVE 8.95
SAM SMITH HOW TO GET FASTER PIZZA 29.95
WILLIAM WHITE HOW TO MANAGE THE MANAGER 31.95
LISA WHITE SHORTEST POEMS 39.95
20 rows selected.

You could use this:
SELECT lname, fname, title, retail
FROM author a
INNER JOIN bookauthor ba
ON a.id = ba.author_id
INNER JOIN books b
ON b.id = ba.book_id
WHERE (ba.author_id, ba.retail) IN (
SELECT ba1.author_id, MAX(b1.retail)
FROM books b1
INNER JOIN bookauthor ba1
ON ON b1.id = ba1.book_id
GROUP BY ba1.author_id
);
Do not use NATURE JOIN. This is bad way of join, for all learner and programmer.
(And change author_id, book_id to column name of your specific table)
Other way:
SELECT lname, fname, title, retail
FROM author a
INNER JOIN bookauthor ba
ON a.id = ba.author_id
INNER JOIN books b
ON b.id = ba.book_id
INNER JOIN(
SELECT ba1.author_id, MAX(b1.retail) retail
FROM books b1
INNER JOIN bookauthor ba1
ON ON b1.id = ba1.book_id
GROUP BY ba1.author_id
) mr
ON
ba.author_id = mr.author_id
AND ba.retail = mr.retail
;

This can be solved using ether an inner join:
select lname, fname, title, retail
from author natural join bookauthor
natural join books
inner join (select max(retail) as max_retail, authorid
from books
group by authorid) b
on books.authorid = b.authorid and books.retail = b.max_retail
or a correlated subquery:
select lname, fname, title, retail
from author natural join bookauthor
natural join books
where retail=(select max(retail)
from books b where b.authorid=author.authorid);
Please note, because you are using the natural join it is impossible for us to know the actual column names you used for the joins. Therefore I have assumed that the authorid foreign key is called authorid

Related

How to join two tables with three pairs

I have two tables that I want to combine (join) in SQL.
Table 1 Persons:
Person _Id
First_name
Last_name
135790
John
Smith
246801
Lucas
Williams
054953
George
Johnson
460235
Adam
White
Table 2 Loans:
Borrower_Id
resident1_id
resident2_id
135790
246801
054953
460235
054953
135790
054953
246801
135790
The expected result:
Borrower_FN
Borrower_LN
resident1_FN
resident1_LN
resident2_FN
resident1_LN
John
Smith
Lucas
Williams
George
Johnson
Adam
White
George
Johnson
John
Smith
George
Johnson
Lucas
Williams
John
Smith
How can I join it?
This is a way you can achieve the result:
select p.First_name as Borrower_FN, p.Last_name as Borrower_LN,
p2.First_name as resident1_FN, p2.Last_name as resident1_LN,
p3.First_name as resident2_FN, p3.Last_name as resident2_LN
from Loans l
inner join Persons p on p.Person_id = l.Borrower_id
inner join Persons p2 on p2.Person_id = l.resident1_id
inner join Persons p3 on p3.Person_id = l.resident2_id

SQL join manager from same table onto a row with their employees

To start, here's a dummy table I've made to show the data I'm working with:
employee
title
division
email
Boss Person
boss
o
bp#email
John Smith
supervisor
a
jos#email
Jane Smith
supervisor
b
jas#email
Leo Messi
employee
a
lm#email
Amanda Kessel
employee
a
ak#email
Derek Jeter
employee
b
dj#email
I want to end up with the following info:
employee
title
division
email
supervisor_name
supervisor_email
Boss Person
boss
o
bp#email
NULL
NULL
John Smith
supervisor
a
jos#email
Boss Person
bp#email
Jane Smith
supervisor
b
jas#email
Boss Person
bp#email
Leo Messi
employee
a
lm#email
John Smith
jos#email
Amanda Kessel
employee
a
ak#email
John Smith
jos#email
Derek Jeter
employee
b
dj#email
Jane Smith
jas#email
I've looked through and tried documentation at:
https://www.sqltutorial.org/sql-self-join/
SQL Server : LEFT JOIN EMPLOYEE MANAGER relationship
One of the big differences here is I don't have any employee or manager id column to work with.
If you're a supervisor for a division, ie John Smith is a supervisor in division a, then you manage all the employees in division a. Meanwhile, all the supervisors answer to the boss in division o, while the boss answers to no one.
Here is the best code I've tried so far:
select e.*, b.employee as supervisor, b.email as supervisor_email
from employees e, employees b
where b.division = e.division
and
b.title like '%supervisor%'
This got me close, it returned:
employee
title
division
email
supervisor_name
supervisor_email
John Smith
supervisor
a
jos#email
John Smith
jos#email
Jane Smith
supervisor
b
jas#email
Jane Smith
jas#email
Leo Messi
employee
a
lm#email
John Smith
jos#email
Amanda Kessel
employee
a
ak#email
John Smith
jos#email
Derek Jeter
employee
b
dj#email
Jane Smith
jas#email
So, it got the employee info right, but left out the Boss record and placed the supervisors as their own supervisor. I think I need some kind of case or if statement here, but I'm not sure.
Please let me know if this makes sense or if any further clarification is needed.
You could try using a LEFT JOIN and work with two conditions:
when division is the same and we're dealing with the relationship employee < supervisor
when the relationship is supervisor < boss
Here's how I did it:
SELECT t1.*,
t2.employee,
t2.email
FROM tab t1
LEFT JOIN tab t2
ON (t1.division = t2.division AND
t2.title = 'supervisor' AND
t1.title = 'employee')
OR (t2.title = 'boss' AND
t1.title = 'supervisor')
You'll find an SQL fiddle here.
If you want to update the current table (if columns are available), you can do the following (more or less the same as #lemon) :
UPDATE testing t1 JOIN testing t2 ON t2.`division`=t1.division OR t2.division="o" SET
t1.supervisor_name=t2.`employee`, t1.supervisor_email=t2.email
WHERE (CASE
WHEN t1.`title`="employee" THEN t2.title="supervisor"
WHEN t1.`title`="supervisor" THEN t2.title="boss"
END);
SELECT * FROM testing;

create a table based on one row of one to another table

I created different tables for each authors because each author table has different column names.
Table Author
Author_ID FirstName LastName
1 Rock Smith
2 Edward Thomas
Table Author Books
Author_ID BookName
1 Book1
1 Book2
1 Book3
1 Book4
1 Book5
I want result like this
Result Table
FirstName LastName BookName
Rock Smith Book1
Rock Smith Book2
Rock Smith Book3
Rock Smith Book4
Rock Smith Book4
Table New_Authors
Author_ID Author_Table
1 Rock_Smith
2 Edward_Thomas
Talbe Rock_Smith
FirstName LastName BookName
Rock Smith Book1
Rock Smith Book2
Rock Smith Book3
Rock Smith Book4
Rock Smith Book4
Is it possible to get all the Rock_Smith table info on querying New_Authors table?
To return the data from those 2 tables, you can run this query:
SELECT a.FirstName, A.LastName, b.BookName
FROM Author A inner join AuthorBooks B on A.Author_ID = B.Author_ID
If you wanted to create a 3rd table based on the query you would do:
Step 1) Create your Table.
Step 2) Run your query:
SELECT a.FirstName, A.LastName, b.BookName
INTO [NewTable]
FROM Author A inner join AuthorBooks B on A.Author_ID = B.Author_ID
This is a simple one to many relationship achieved by a LEFT JOIN:
SELECT a.LastName, a.FirstName, b.BookName
FROM Authors a LEFT JOIN AuthorBooks b ON b.Author_ID = a.Author_ID
ORDER BY LastName, FirstName, BookName

Is it joins again in ORACLE

Here's the problem:
List the title, authors first and last names and year to date sales for books whose authors have addresses in California and Utah.
the desc tables:
SQL> desc authors
Name
--------------------------
AUTHOR_ID
AUTHOR_LNAME
AUTHOR_FNAME
PHONE
ADDRESS
CITY
STATE
ZIP
SQL> desc title_authors
Name
--------------------------
AUTHOR_ID
TITLE_ID
AUTHOR_ORD
ROYALTY_SHARE
SQL> desc titles
Name
--------------------------
TITLE_ID
TITLE
TYPE
PUBLISHER_ID
PRICE
ADVANCE
YTD_SALES
CONTRACT
NOTES
PUBLICATION_DATE
Here's what Ive tried w/ results......
SQL> SELECT AUTHORS.AUTHOR_FNAME, AUTHOR_LNAME, TITLES.TITLE, TITLES.YTD_SALES
2 FROM AUTHORS
3 JOIN TITLE_AUTHORS ON AUTHORS.AUTHOR_ID = TITLE_AUTHORS.AUTHOR_ID
4 JOIN TITLES ON TITLE_AUTHORS.TITLE_ID = TITLES.TITLE_ID
5 WHERE STATE = 'CA'
6 OR STATE = 'UT';
AUTHOR_FNAME AUTHOR_LNAME TITLE YTD_SALES
-------------------- ---------------------------------------- ---------------------------------------- ----------
Marjorie GreeN The Busy Executive's Database Guide 4095
Marjorie GreeN You Can Combat Computer Stress! 18722
Dick StrAight Straight Talk About Computers 4095
Note 3 full results returned.
Next trial, which Ive tried various versions of, returns 3 full records, but the entire authors list:
AUTHOR_FNAME AUTHOR_LNAME TITLE YTD_SALES
-------------------- ------------ ---------------------------------------- ----------
Marjorie GreeN The Busy Executive's Database Guide 4095
Marjorie GreeN You Can Combat Computer Stress! 18722
Dick StrAight Straight Talk About Computers 4095
Albert Ringer
Ann Dull
JOHNSON White
Chastity Locksley
Anne RINGER
Stearns MacFeatHer
Anne RINGER
Michael O'Leary
Stearns MacFeatHer
Livia Karsen
Abraham BeNNet
Albert Ringer
Michael O'Leary
Sheryl Hunter
Cheryl Carson
Chastity Locksley
What is this? Is it blocked somehow? I can see the entire tables individually.
Any one?
Try this,
SELECT AUTHORS.AUTHOR_FNAME, AUTHOR_LNAME, TITLES.TITLE, TITLES.YTD_SALES
FROM AUTHORS
INNER JOIN TITLE_AUTHORS ON AUTHORS.AUTHOR_ID = TITLE_AUTHORS.AUTHOR_ID
INNER JOIN TITLES ON TITLE_AUTHORS.TITLE_ID = TITLES.TITLE_ID
WHERE STATE = 'CA' OR STATE = 'UT';

Should I Use a Self-Join

If I have a table...
ID Name Manager
0 Joe Sue
1 Jake Tom
0 Joe Tom
2 Larry Red
2 Larry Paul
1 Jake Paul
I want the output to be....
ID Name Manager1 Manager2
0 Joe Sue Tom
1 Jake Tom Paul
2 Larry Red Paul
Thanks...
If I have understood your request properly, yes, something like would produce the results you are looking for.
SELECT
t1.Name Name,
t1.Manager Manager1,
t2.Manager Manager2
FROM
Table t1
inner join Table t2 on t1.Manager = t2.Name
Of course a foreign key back to the index column would be preferential to strong comparisons for performance.
Yeah, if your table was called 'Managers':
SELECT Mgr1.ID,Mgr1.Name,Mgr1.Manager,Mgr2.Manager
FROM Managers AS Mgr1
LEFT JOIN Managers AS Mgr2
ON Mgr1.ID=Mgr2.ID
If your keeping the tables a join would be best.
If you hate joins, you could combine the max and min managers, and even then it would work if there is always 2 managers and they can't have the same name.
The below should work if I remember how to join up 2 queries correctly. but i would advise to see if it is possible to rework your table, have a separate table linking people to each other in a manager employee relation.
SELECT DISTINCT
F.ID, F.Name, S.Manager, F.Manager
FROM
(SELECT
ID, Name, MIN(manager) manager
FROM Managers
GROUP BY ID, Name) F,
(SELECT
ID, Name, MAX(manager) manager
FROM Managers
GROUP BY ID, Name) S
WHERE
F.ID = S.ID
AND S.Manager <> F.Manager
AND F.ID < S.ID