SQL Homework - "IN" Subquery - sql

yes this is a homework question, but I'm giving it honest effort and I'm not asking you to do it for me, just point me in the right direction! :)
So I have a set of questions concerning the SQL IN subquery, and while I understand what it does I'm having trouble applying it in these situations.
The first question:
1) Use the In subquery technique to list the customer number, customer name and phone for customers who have paid either by visa or mc. Sort
by customer name.
This one I believe I got:
SELECT DISTINCT
tblCust.CustomerNum, CustomerName, Phone
FROM
tblCust
INNER JOIN tblOrd ON
tblCust.CustomerNum=tblOrd.CustomerNum
WHERE
tblOrd.PayMethod IN ("visa", "mc")
ORDER BY CustomerName;
But the next one just makes no sense to me:
2) Use the In subquery technique to list from tblCust the customer number, customer name and state for customers who have a state
description that begins with “co”.
Shouldn't I be using the LIKE operator for this instead of IN?
So far I have:
SELECT
CustomerNum, CustomerName, StateProv
FROM
tblCust
INNER JOIN tblState ON
tblCust.StateProv = tblState.StateProv
WHERE
tblState.StateProvDesc IN
And I don't know what to put after the IN, if I were using LIKE I would say
...StateProvDesc LIKE "co%"
and be done with it, but I don't think that's what my teacher wants.
Finally, the third question:
3) Use the In subquery technique to list from tblCust the customer
name, country for customers who have at least one order in the range
of $90,000-$120,000. Sort by country then customer name.
Shouldn't between be used for a range of numbers?
Thanks for anything you guys can think of!
using microsoft access by the way

I think what the prof wants you to do is write a subquery within the IN clause. You can actually put a select statement within IN() like this:
SELECT
CustomerNum, CustomerName, StateProv
FROM
tblCust
WHERE StateProv IN(SELECT StateProv FROM tblState WHERE StateProvDesc LIKE 'co%')

I think the instructor wants you to change the query to use ... IN (SELECT ... FROM ...) style instead of the inner join.
You can work on these queries from the back of the description, like this:
...a state description that begins with “co”.
-- Inner query
SELECT StateProv
FROM tblState
WHERE StateProvDesc LIKE `co%`
Now that you have this, you can compose the outer query:
list from tblCust the customer number, customer name and state for customers who have...
SELECT
CustomerNum, CustomerName, StateProv
FROM
tblCust
WHERE tblCust.StateProv IN (
-- Your inner query goes here
)

Related

Selecting fields that are not in GROUP BY when nested SELECTS aren't allowed

I have the tables:
Product(code (PK), pname, (....), sid (FK)),
Supplier(sid(PK), sname, (....))
The assignment is:
Find Suppliers that supply only one product. Display their name (sname) and product name (pname).
It seem to me like a GROUP BY problem, so I used:
SELECT sid FROM
Product GROUP BY sid
HAVING CAST(COUNT(*) AS INTEGER) = 1;
This query have found me the list of sid's that supply one product only, but now I have encountered a problem:
The assignment forbids any form of nested SELECT queries.
The result of the query I have written has only one column. (The sid column)
Thus, I am unable to access the product name as it is not in the query result table, and if I would have added it to the GROUP BY statement, then the grouping will based on product name as well, which is an unwanted behavior.
How should I approach the problem, then?
Note: I use PostgreSQL
You can phrase the query as:
SELECT s.sid, s.sname, MAX(p.pname) as pname
FROM Product p JOIN
Supplier s
ON p.sid = s.sid
GROUP BY s.sid, s.sname
HAVING COUNT(*) = 1;
You don't need to convert COUNT(*) to an integer. It is already an integer.
You could put
max(pname)
in the SELECT list. That's an aggregate, so it would be fine.

SQL display ID of any customer who has never placed an order, using set-based operations only

Couldn't find anything on this, using set-based operations.
Not sure if I'm on the right track, but I have 2 guesses on how to do this, but I'm not sure if I'm even close, or if MINUS is the right set-based operation to use:
SELECT customerid
FROM customer
MINUS
SELECT orderid
FROM custorder
WHERE custorder IS NULL;
or
SELECT customerid
FROM customer
MINUS
SELECT orderid
FROM custorder;
Suggestions on how to improve or what to change? Any help is appreciated.
Could someone also possibly explain when to use UNION, UNION ALL, or INTERSECT on a similar sample like this?
Also, I'm not sure if I need these in 2 different tables or not. In this database, 2 of these tables are CUSTOMER (has customerid) and CUSTORDER (has customerid and orderid). Here's a screenshot of the table values if you wanted to see: https://imgur.com/a/vHMC4
NOTE: I HAVE TO USE SET-BASED OPERATIONS ONLY FOR FULL CREDIT
probably more like
select customerid
from customer
MINUS
select customerid
from custorder;
you need to MINUS off the same type of values from the set
I would use not exists:
select c.*
from customer c
where not exists (select 1
from custorder co
where co.customerid = c.customerid
);
You can do something similar with not in and left join/where.
The set-based approach is:
SELECT customerid
FROM customer
MINUS
SELECT customerid
FROM custorder;
The advantage of the first method is that you can select additional columns from customer.

ORDER BY + IN statement?

The marketing department wants to focus on the customers from Noth America first. Get the ID, last name and country of all customers. Build the list by bringing up the customers living in Canada and in the USA first, and finally order them by ID. Tip: use the IN expression in the ORDER BY clause.
I've tried many times
SELECT CustomerID, LastName, Country
FROM Customer
ORDER BY Country IN ('Canada', 'USA'), CustomerID
but it doesn't seem to work, as it takes the specified fields from all customers in the order they appear in the original table (which is also ordered by ID), even if I remove CustomerID from the ORDER BY clause, whithout caring to which country they belong to.
What should I do? I'm really new to SQL, and have no idea on how to fix this.
Edit: WHERE ins't suitable at all, as I need to take in consideration all customers, only making sure the Canadian and American ones appear at the top of the list.
Also I'm unsure statements like UNION, AS, EXCEPT and things like that are meant to be used, because the tutorial didn't go that deep already.
Not every DBMS has a boolean datatype. So the result of
Country IN ('Canada', 'USA'),
which is a boolean, can not be sorted in these DBMS.
You can use a CASE expression, however, to assign a value:
SELECT CustomerID, LastName, Country
FROM Customer
ORDER BY CASE WHEN Country IN ('Canada', 'USA') THEN 1 ELSE 2 END, CustomerID;
SELECT CustomerID, LastName, Country
FROM Customer
ORDER BY Country IN ('Canada', 'USA') desc, CustomerID asc
IN expression don't return value so you can't sort
You can try:
SELECT CustomerID, LastName, Country
FROM Customer
WHERE Country='Canada'
UNION ALL
SELECT CustomerID, LastName, Country
FROM Customer
WHERE Country='USA'
ORDER BY CustomerID
Using ORDER BY with UNION, EXCEPT, and INTERSECT When a query uses the
UNION, EXCEPT, or INTERSECT operators, the ORDER BY clause must be
specified at the end of the statement and the results of the combined
queries are sorted. The following example returns all products that
are red or yellow and sorts this combined list by the column
ListPrice.
https://msdn.microsoft.com/en-us/library/ms188385.aspx#Union

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.

SQL WHERE <from another table>

Say you have these tables:
PHARMACY(**___id_pharmacy___**, name, addr, tel)
PHARMACIST(**___Insurance_number___**, name, surname, qualification, **id_pharmacy**)
SELLS(**___id_pharmacy___**, **___name___**, price)
DRUG(**___Name___**, chem_formula, **id_druggistshop**)
DRUGGISTSHOP(**___id_druggistshop___**, name, address)
I think this will be more specific.
So, I'm trying to construct an SQL statement, in which I will fetch the data from id_pharmacy and name FROM PHARMACY, the insurance_number, name, and surname columns from PHARMACIST, for all the pharmacies that sell the drug called Kronol.
And that's basically it. I know I'm missing the relationships in the code I wrote previously.
Note: Those column names which have underscores left and right to them are underlined(Primary keys).
The query you've written won't work in any DBMS that I know of.
You'll most likely want to use some combination of JOINs.
Since the exact schema isn't provided, consider this pseudo code, but hopefully it will get you on the right track.
SELECT PH.Ph_Number, PH.Name, PHCL.Ins_Number, PHCL.Name, PHCL.Surname
FROM PH
INNER JOIN PHCL ON PHCL.PH_Number = PH.Ph_Number
INNER JOIN MLIST ON MLIST.PH_Number = PH.PH_Number
WHERE MLIST.Name = "Andy"
I've obviously assumed some relationships between tables that may or may not exist, but hopefully this will be pretty close. The UNION operator won't work because you're selecting different columns and a different number of columns from the various tables. This is the wrong approach all together for what you're trying to do. It's also worth mentioning that a LEFT JOIN may or may not be a better option for you, depending on the exact requirements you're trying to meet.
Ok, try this query:
SELECT A.id_pharmacy, A.name AS PharmacyName, B.Insurance_number,
B.name AS PharmacistName, B.surname AS PharmacistSurname
FROM PHARMACY A
LEFT JOIN PHARMACIST B
ON A.id_pharmacy = B.id_pharmacy
WHERE A.id_pharmacy IN (SELECT id_pharmacy FROM SELLS WHERE name = 'Kronol')