Need some assistance with 2 SQL queries [closed] - sql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I need some help with my exam, there are 2 questions but I don't know how to join them and which SQL statements I need.
Write a SQL statement which displays the employee id, last name,and salary of any employee whose salary is above the price of the most expensive product.
Write a SQL statement which displays the customer id of customers who purchased the product with product_id 1 but so far never purchased the product with product_id 3.
It would be nice if somebody explain me the solution.

With the understanding this is a practice exam, and that you don't have access to the tables/values....
You really should show what you've tried... but since you're new...
Question 1:
Return employeeID, last name and salary of all employees who have a salary greater than the price of the most expensive product (like how they avoided using the word max there...)
So this uses a subquery to get the max price from products and simply compares salary against it.
SELECT Employee_ID, Last_Name, Salary
FROM employees
WHERE salary > (Select max(price) from Products);
Question 2:
Generate two sets one for product_ID of 1 one for product_ID of 3 and make sure those with 1 are not in the group with 3.
and this uses a correlated subquery (notice how the PUR alias is in the subquery? that's why it's correlated)
So the first query gets all the customers buying product 1. The 2nd query finds all the customers buying product 3. and since we want only those customers who bought 1 not 3, we correlate the queries using not exists and we have our answer.
Exists - usually fastest as it can early exit the subquery once a single record for a customer is found.
SELECT Distinct PUR.Customer_ID
FROM purchases PUR
WHERE PRODUCT_ID = 1
and not exists (SELECT 1
FROM Purchases PUR2
WHERE Product_ID = 3
and PUR.Customer_ID = PUR2.Customer_I
There are 2-3 ways of doing this. I find the above the most efficient in most cases. However you could also do it by... a self join; or using an not IN statement
Self LEFT join (works great if you need data from multiple tables
We self join on purchases but filter each table instance to be for a specific product. we use left join as we want all records with product Id 1 and where a match is found in p2, we want to EXCLUDE those records so if the customer_ID is null that means they have no product 3 purchases
SELECT Distinct P1.customer_ID
FROM Purchases P1
LEFT JOIN Purchase P2
on P1.customer_Id = P2.customer_ID
and P2.Product_ID = 3
WHERE P1.Product_ID = 1
and P2.customer_ID is null
not in (usually slowest but works fine if subquery is for a VERY Small datasets)
SELECT Distinct PUR.Customer_ID
FROM purchases PUR
WHERE PRODUCT_ID = 1
and customer_ID not in (SELECT Customer_Id
FROM Purchases
WHERE Product_ID = 3)
Notice that neither of the 1st two answers uses a join; though a correlated subquery is close.

Related

Interview Question about SQL group by and having

This problem is from the following
https://www.programmerinterview.com/index.php/database-sql/advanced-sql-interview-questions-and-answers/
Assume we have two tables:
Salesperson
ID Name Age Salary
Orders
Number order_date cust_id salesperson_id Amount
The question is following:
We want to retrieve the names of all salespeople that have more than 1 order from the tables above. You can assume that each salesperson only has one ID. I would probably also assume that names are all distinct.
My answer was this.
select Name from
salesperson S inner join Orders O
on S.ID=O.salesperson_id
group by Name
having count(number) >=2
However, the given answer is following:
SELECT Name
FROM Orders inner join Salesperson
On Orders.salesperson_id = Salesperson.ID
GROUP BY salesperson_id, NAME
Having count(salesperson_id) > 1
If name and salesperson_id is one to one, is there any reason we have to add salesperson_id into the group by statement here? Also, if name and salesperson_id relationship is just one to one, wouldn't count(salesperson_id) be always 1 if we group by salesperson_id, name?
I was a bit confused about this, and I was wondering if anybody encountered this problem before and found this weird as well.
Both your solution and the accepted one are functionally identical, except for the GROUP BY clause.
The likely reason why the accepted solution is aggregating both by Name and salesperson_id is that it could be the case that two or more salespeople happen to have the same name. Should this occur, your query would report only a single name, but with aggregate results from more than one salesperson. But, the combination of salesperson_id and Name should always be unique.
Other than this, I actually prefer your version, and I would start joining from the salesperson table out to the Orders table.

Querying records that meet muliple criteria

Hi I’m trying to write a query and I’m struggling to figure out how to go about it.
I have a suppliers table and a supplier parts table I want to write a query that lists suppliers that have specified related Parts in the supplier parts table. If a supplier doesn’t have all specified related parts then they should not be listed.
At the moment I have written a very basic query that lists the supplier if they have a related supplier part that meets the criteria.
SELECT id ,name
FROM
efacdb.dbo.suppliers INNER JOIN [efacdb].[dbo].[spmatrix] ON
id = spmsupp
WHERE spmpart
IN ('ALUM_5083', 'ALUM_6082')
I only want to show the supplier if they have both parts related. Does anyone know how I could do this?
Use a subquery with counting distinct occurences:
select * from suppliers s
where 2 = (select count(distinct spmpart) from spmatrix
where id = spmsupp and spmpart in ('ALUM_5083', 'ALUM_6082'))
As a note, you can modify your query to get what you want, just by using an aggregation:
SELECT id, name
FROM efacdb.dbo.suppliers INNER JOIN
[efacdb].[dbo].[spmatrix]
ON id = spmsupp
WHERE spmpart IN ('ALUM_5083', 'ALUM_6082')
GROUP BY id, name
HAVING MIN(spmpart) <> MAX(spmpart);
If you know there are no duplicates, then having count(*) = 2 also solves the problem.

ambiguous column name error [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have two tables, and I want to connect the tables by CustomerID (CustomerID is same for two tables). So I used my query like:
SELECT
Cus.CustomerID
FROM
Customers AS Cus
JOIN
Payments AS Pay ON Cus.CustomerID = Pay.CustomerID
WHERE
CustomerID = 2
And it shows an error:
'CustomerID' in where clause is ambiguous
How can I resolve ambiguous column name error in a way that does not add the table name before CustomerID?
Since it doesn't know which CustomerID to use in your where clause CustomerID = 2, you should specify which to use:
SELECT
Cus.CustomerID
FROM
Customers AS Cus
JOIN
Payments AS Pay
ON
Cus.CustomerID = Pay.CustomerID
WHERE
Cus.CustomerID = 2
It doesn't matter if you use Cus.CustomerID or Pay.CustomerID since they will always be the same in your current statement (since you equal them in your join).
The ambigious part is here:
WHERE
CustomerID = 2
Both tables have this column you need to be explict either:
Cus.CustomerID
or
Pay.CustomerID
[I]n a way that does not add the table name before CustomerID
You can use a sub-query.
SELECT CustomerID
FROM
(
SELECT
Cus.CustomerID
FROM
Customers AS Cus
JOIN
Payments AS Pay
ON
Cus.CustomerID = Pay.CustomerID
) query
WHERE CustomerID = 2
Is this a good way? No. This may force the query plan to use a scan instead of a seek if CustomerID is an indexed field (which it should be since this is being joined on).

Select Max in a table to get name in other table SQL [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have 2 tables
Players
Pnr
Pname
Padress
Pcity
Tickets
Tnr
Pnr
Date
Costs
I want to get the name of the player with the highest Ticket Cost from the database with Select. And I want to know who has got a Ticket in May. I also want to know who has never got a Ticket.
How do I get each of these?
Pnr is the primary key of Players and is connected with Pnr from Tickets
I've tried
SELECT MAX(Costs) from Players, Tickets
Where max()
I hope i understand correctly. Try the following query. I think it will still have some errors, but you can comment them here and I will try to correct them.
select top 1 Pname from Players
inner join Tickets on Players.Pnr = Tickets.Pnr
where Date > 1.05.2014 and Date <31.05.2014
order desc by Tickets.Costs
For highest ticket cost:
SELECT P.*,T.Tnr,T.Date,T.cost
FROM Players P JOIN
Tickets T ON T.Pnr=B.Pnr
WHERE T.Cost= SELECT MAX(Cost) from Tickets
For player who never got a ticket:
SELECT P.*
FROM Players P LEFT JOIN
Tickets T ON T.Pnr=B.Pnr
WHERE T.Tnr IS NULL
AND T.Pnr IS NULL
AND T.Date IS NULL
AND T.Costs IS NULL

How do you join three tables in Oracle? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I'm having a hard time joining three separate tables in Oracle. I'm never joined three tables before so I'm not well versed. My theory is below:
SELECT customer_num WHEN customer_num IS 104 -198, order_num
FROM orders INNER JOIN items
ON order_num, stock_num
INNER JOIN stock
ON stock_num, description
Essentially, I'm trying to start with the ORDERS table and pull the customer number (customer_num) specifically customer number 104 -108 and the order_num from the orders table. Then attach the orders table to the Items table and attach the order_num and stock_num, and lastly attach the stock table and pull out the stock_num and description.
Your syntax is all over the place, and wouldn't work for a two-table join, or even querying a single table. Not sure where you got WHEN from, or the order of your clauses. Please review the SQL reference to see how to join and how to filter. Anyway...
You seem to want something like this:
SELECT o.customer_num, o.order_num, i.stock_num, s.description
FROM orders o
INNER JOIN items i ON i.order_num = o.order_num
INNER JOIN stock s ON s.stock_num = i.stock_num
WHERE o.customer_num BETWEEN 104 AND 198;
The WHERE clause is being applied to the orders table to restrict which customers' orders you get. I've assumed from your description that the orders and items tables have a common order_num column you can join on; and that the items and stock tables have a common stock_num column you can join on.
As OldProgrammer said, it would be helpful to include your table schemas in the question so assumptions don't need to be made, and showing sample data and expected output for that data would clarify what you're trying to do.
It should look something like this (based on the limited information about the schema)...
SELECT
O.CUSTOMER_NUM,
O.ORDER_NUM,
S.STOCK_NUM,
S.DESCRIPTION
FROM
ORDERS O,
ITEMS I,
STOCK S
WHERE
I.CUSTOMER_NUM >= 104
AND I.CUSTOMER_NUM <= 198
AND O.ORDER_NUM = I.ORDER_NUM
AND I.STOCK_NUM = S.STOCK_NUM
The syntax for a JOIN is:
TableExpression [ INNER ] JOIN TableExpression
{
ON booleanExpression | USING clause
}
The booleanExpression is what the tables will be linked by. So, in your example, something like this:
SELECT customer_num WHEN customer_num IS 104 -198, order_num
FROM orders INNER JOIN items
ON orders.<some_column> = items.<some_column>
INNER JOIN stock
ON items.<some_column> = stock.<some_column>