My professor said I did not tie between tables, now I want to ask how to tie tables, this are two of my example I did incorrect.
Query2 - no ties between tables
SELECT CustomerID, CompanyName, [Order Details].UnitPrice
FROM Customers, [Order Details]
WHERE ((([Order Details].UnitPrice)>=50));
Query3 - no ties between tables
SELECT ProductID, ProductName, ShippedDate
FROM Products, Orders
where Orders.ShippedDate between ('1996-07-01') and ('1996-07-31')
ORDER BY Orders.ShippedDate;
Basically your query is missing a join conditions between the two tables. Without it, you get a cartesian products of the rows from both tables.
This is where the join syntax comes into play. For example for the second query, assuming that products and orders relate through column product_id:
select p.productid, p.productname, o.shippeddate
from products p
inner join orders o on o.product_id = p.product_id
where o.shippeddate >= '1996-07-01' and o.shippeddate < '1996-08-01'
order by o.shippeddate;
Other improvements to the query:
table aliases make the query easier to write and read
half-open intervals for date comparisons are handy: they properly handle the time portion of the dates (if any)
Related
I have a table of orders, and a table of products contained in these orders. (The products-table has order_id, a foreign key referring to orders.id).
I would like to query the number of products contained in each order. However, I also want orders to be contained in the results if they do not contain any products at all.
This means that a simple
SELECT *, COUNT(*) n_products FROM `orders` INNER JOIN `products` on `products.order_id` = `orders.id` GROUP_BY `order_id`
does not work, since orders without any products disappear.
Using a LEFT OUTER JOIN instead would add rows without product-information, but the distinction between an order with 1 product and an order with 0 products is lost.
What am I missing here?
You need a left join here, and you should be counting some column from the products table:
SELECT
o.*,
COUNT(p.order_id) AS n_products
FROM orders o
LEFT JOIN products p
ON p.order_id = o.id
GROUP BY
o.id;
Note that I assume that Postgres would allow grouping by orders.id and then selecting all columns from that table. If not, then you would only be able to select o.id in addition to the count.
First of all, I'm practicing with Northwind database (Microsoft creation).
The table design I'm working with is:
The question I'm trying to solve is:
Which Product is the most popular? (number of items)
Well, my query was:
SELECT DISTINCT
P.ProductName
FROM
Products P,
[Order Details] OD,
Orders O,
Customers C
WHERE
C.CustomerID = O.CustomerID
and O.OrderID = OD.OrderID
and OD.ProductID = P.ProductID
and P.UnitsInStock = (SELECT MAX(P.UnitsInStock) Items
FROM Products P)
Now, I had exactly one result as they asked:
ProductName
1 Rhönbräu Klosterbier
Yet, I doublt that my query was good. Do I really need a SELECT within a SELECT?
It feels like duplication for some reason.
Any help would be appreciated. Thanks.
To get the most popular product (bestselling product) use query
SELECT ProductName, MAX(SumQuantity)
FROM (
SELECT P.ProductName ProductName,
SUM(OD.Quantity) SumQuantity
FROM [Order Details] OD
LEFT JOIN Product P ON
P.ProductId = OD.ProductID
GROUP BY OD.ProductID
) Res;
Does the most units in stock necessarily equate to the most popular product? I don't think that is always a true statement (It could even be the opposite in fact.).
To me the question is asking, which is the most popular product sold. If you think about it that way, you'd be looking at the amount sold for each product and selecting the product with the most sold.
Does that make sense?
With regards to your specific query, the query only utilizes the Products table. You make joins, but they are not used at all in the query and should get overlooked by the query optimizer.
I would personally rewrite your query as the following:
SELECT
P.ProductName
FROM
Products P
INNER JOIN
(SELECT
MAX(P.UnitsInStock) AS Items
FROM Products P) maxProd
ON P.UnitsInStock= maxProd.Items
About your question, it is perfectly acceptable to utilize a subquery (the select in the where clause). It is even necessary at times. Most of the time I would use an Inner Join like I did above, but if the dataset is small enough, it shouldn't make much difference with query time.
In this scenario, you should rethink the question that is being asked and think about what being the most popular item means.
Rethinking the problem:
Let's look at the datasets that you've shown above. Which could be used to tell you how many products have been sold? A customer would have to order a product, right? Looking at the two tables that are potentially applicable, one contains details about number of items sold, quantity, or you could think of popularity in terms of the number of times appearing in orders. Start with that dataset and use a similar methodology to what you've done, but perhaps you'll have to use a sum and group by. Why? Perhaps more than one customer bought the item.
The problem with the dataset is it doesn't tell you the name of the product. It only gives you the ID. There is a table though that has this information. Namely, the Products table. You'll notice that both tables have the Product ID variable, and you are able to join on this.
You can find the most popular product by counting the number of orders placed on each product .And the one with most number of order will be the most popular product.
Below script will give you the most popular product based on the the number of orders placed .
;WITH cte_1
AS(
SELECT p.ProductID,ProductName, count(OrderID) CNT
FROM Products p
JOIN [Order Details] od ON p.ProductID=od.ProductID
GROUP BY p.ProductID,ProductName)
SELECT top 1 ProductName
FROM cte_1
ORDER BY CNT desc
if you are using SQL server 2012 or any higher version, use 'with ties' for fetching multiple products having same order count.
;WITH cte_1
AS(
SELECT p.ProductID,ProductName, count(OrderID) CNT
FROM Products p
JOIN [Order Details] od ON p.ProductID=od.ProductID
GROUP BY p.ProductID,ProductName)
SELECT top 1 with ties ProductName
FROM cte_1
ORDER BY CNT desc
In your sample code,you tried to pull the product with maximum stock held. since you joined with other tables (like order details etc) you are getting multiple results for the same product. if you wanted to get a product with maximum stock,you can use any of the following script.
SELECT ProductName
FROM Products P
WHERE P.UnitsInStock = (SELECT MAX(P.UnitsInStock) Items
FROM Products P)
OR
SELECT top 1 ProductName
FROM Products P
ORDER BY P.UnitsInStock desc
OR
SELECT top 1 with ties ProductName --use with ties in order to pull top products having same UnitsInStock
FROM Products P
ORDER BY P.UnitsInStock desc
So in a practice site there is a question:
Which Product is the most popular? (number of items)
This means that There are Customers, and they want to know the most popular Ordered Product by the Customers(Overall Orders of TOP 1 ordered Product).
I Sincerely do not know How to solve this one.
Any help?
What I've tried so far is:
SELECT TOP(1) ProductID, ProductName
FROM Products
GROUP BY ProductID, ProductName
ORDER BY COUNT(*) DESC
But that's far from what they have asked.
In this one, I just get the top 1 Product with the lowest count, but that doesn't mean anything about the customers who ordered this product.
That only means that this specific Item could have been at low quantity and still is lower then the others, while the others were very high quantity and now just low (but still not low enough)
I hope I was clear enough.
If the data exists in that table, you might just need to order by something more sophisticated than count, like summing the quantity (if that column exists). Also, if ProductID and ProductName are already unique identifiers, note that you don't need the group by and sum at all.
SELECT TOP(1) ProductID, ProductName
FROM Products
GROUP BY ProductID, ProductName
ORDER BY SUM(Quantity) DESC
I don't know what your keys are, but it sounds like you actually want to be counting how many times it was ordered by customers, so you may need to join on the Customers table. I am assuming here that you have a table Orders, that has one line per order and shares the ProductID key. I also assume that ProductID is unique in Products (which may not be true based on your first query).
SELECT TOP(1) Products.ProductID, Products.ProductName
FROM Products
LEFT JOIN Orders
ON Orders.ProductID = Products.ProductID
GROUP BY Products.ProductID, Products.ProductName
ORDER BY COUNT(Orders.OrderID) DESC
This really depends on what tables and keys you have available to you.
Select top 1 P.ProductID,P.ProductName,Sum(OD.Quantity)AS Quantity
From [Order Details] OD
inner join Products P ON P.ProductID = OD.ProductID
Group By P.ProductID,P.ProductName
Order by Quantity Desc
You can workout something like this, (Table name/schema may differ)
with cte_product
as
(
select ProductID,Rank() over (order by Count(1) desc) as Rank from
Orders O
inner join Product P
on P.ProductID = O.ProductID
group by ProductID
)
select P.productID, P.ProductName from
cte_product ct
inner join product p
on ct.productId = p.ProductID
where ct.Rank = 1
Crux is usage of RANK() to get most popular product. Rest you may fetch columns as per need using relevant Joins.
First and foremost - it is a homework assignment, yet I am not asking for anyone to do it. Instead I need help with how to construct the query.
As part of an assignment, using the Northwind database via Microsoft Access, I have to construct this query:
The product ID, product name, and quantity ordered for all products ordered on an order taken by an employee with last name Fuller.
Now, when I construct the query in design mode, this is the code I get:
SELECT Products.ProductID, Products.ProductName, [Order Details].Quantity
FROM Products INNER JOIN ((Employees INNER JOIN Orders ON Employees.EmployeeID = Orders.EmployeeID) INNER JOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID) ON Products.ProductID = [Order Details].ProductID
WHERE (((Employees.LastName)="Fuller"));
As I mentioned earlier, we are not allowed to use Inner Join. After scouring the text/notes thus far I can't find how to go about it. (Very new to SQL)
Would I be rewriting the FROM statement? And if so, do the SELECT and WHERE statements change?
UPDATE: Here is the code as I rewrote it:
SELECT Orders.OrderID, Orders.CustomerID, Orders.ShipCity
FROM Products, Orders, [Order Details], Employees
WHERE
Products.ProductID = [Order Details].ProductID
AND Employees.EmployeeID = Orders.EmployeeID
AND Ordes.OrderID = [Order Details].OrderID
AND Employees.LastName = "Fuller";
I'm having a sort of syntax issue though. Since the Order Details must be enclosed in brackets, it wants to ask for parameter values for what I wrote in the WHERE statement.
The requirement not to use INNER JOIN is a little peculiar and I cannot guarantee this is what was intended for your assignment.
One way to alternatively write a simplistic relationship between two tables is with an IN () subquery, the general form being:
SELECT *
FROM a_table
WHERE some_column IN (
SELECT some_related_column
FROM b_table
WHERE some_condition
)
But since you must represent columns from more than one of your 4 tables in the SELECT list, that form isn't going to work for you. Another way of not explicitly using an INNER JOIN is to use the older implicit joining syntax, in which multiple tables are listed in the FROM clause separated by commas, and their joining conditions placed in the WHERE clause instead of in ON.
The general form is:
SELECT
a_table.col1,
a_table.col2,
b_table.col1
FROM
a_table,
b_table
WHERE
a_table.some_column = b_table.some_related_column
AND some_other_conditions
It being an assignment, I will leave it to you to work out the entire statement, but yours would take a form like
SELECT
Orders.OrderID,
Orders.CustomerID
FROM
Products,
Orders,
[Order Details],
Employees
WHERE
Products.ProductID = [Order Details].ProductID
AND ... (the other table relationships)
AND Employees.LastName = 'Fuller'
Although it is functionally identical to explicit INNER JOINs, this is an older syntax, and is often discouraged nowadays. More discussion is available in this question
I need to get data from multiple tables and put it into a subform.
The SubForm columns are 'product name' and 'quantity' and they need to list out the products relating to the order ID.
The tables in question are:
PRODUCTS(productID,productName)
ORDER(orderID,prodID,quantity)
Where the prodID in ORDER refers to the PRODUCTS table.
As you can see, the problem is that the name of the product is in a different table to the order. So, the data I need to get is:
Products(productName)
Order(quantity)
In relation to the orderID.
How can I use a SQL query to get this data? I am aware of joins and so on, but I just can't see how to apply it.
Thank you. I hope this makes sense.
This is a simple inner join between the two tables to return the rows you want:
SELECT P.PRODUCTNAME, O.QUANTITY
FROM PRODUCTS P INNER JOIN ORDER O ON P.PRODUCTID = O.PRODID
WHERE O.ORDERID = <order id>
SELECT
PRODUCTS.productName AS productName,
`ORDER`.quantity AS quantity
FROM
`ORDER`
INNER JOIN PRODUCTS on `ORDER`.prodID=PRODUCTS.productID
WHERE
..
You migh also want to rename the table ORDER - using reserved words as table names is not the best of styles.
Select p.productname, q.quantity from product_table p, quantity_table q where p.productId = q.productId;