Write a SQL to meet my requirement - sql

I have been trying to solve this problem for a lot of days. But wouldn't. Please help me.
I need a SQL to list product_code, product_name, qty_sold, last_order_date for all the products that have been sold within a date range sorted by the number of quantity sold.
My Table structure:
tbl_product(product_id,product_code,product_name)
tbl_order_detail(order_item_id,order_id,product_id,quantity)
tbl_order(order_id,order_date)

You could use group by to calculate statistics per product. Then you can use sum and max to retrieve the aggregate information required. For example:
select p.product_code
, p.product_name
, sum(od.quantity) as qty_sold
, max(o.order_date) as last_order_date
from tbl_product p
join tbl_order_detail od
on p.product_id = od.product_id
join tbl_order o
on od.order_id = o.order_id
where o.order_date between '2010-01-01' and '2010-02-01'
group by
p.product_code
, p.product_name
order by
sum(od.quantity) desc

select
p.product_code, p.product_name, sum(od.quantity) as qty_sold, max(o.order_date) as last_order_date
from tbl_product p join tbl_order o join tbl_order_detail od on
(p.product_id=o.product_id, o.order_id = od.order_id)
where
order_date between :first_day: and :last_day:
group by product_code, product_name
order by last_order_date
Sorry I can't test this right now.
Keypoints are: use the group by clause to aggregate the quantity and order date values, and use max and sum to find the desired values.
:first_day: and :last_day: are placeholders for the actual values
Hope I helped you

Related

Challenging PostgreSQL SELECT Statement for Northwind Database (NEED HELP - BEGINNER)

I began learning SQL about a month ago and my dad has been giving me practice queries to run
with the Northwind database to help practice my DML. This most recent one he gave me was as follows:
-- Return Month, Product name, SalesForMonth for highest selling product in each
-- month in 1997. (see issues with creating said query below)
(I am currently using PostgreSQL on pgAdmin4)
I was able to come up with the following query that returns the required columns with the correct information for ONLY a single month:
SELECT CAST( EXTRACT( MONTH FROM o.orderdate) AS integer) AS Month, p.productname,
ROUND(CAST(SUM(od.quantity * od.unitprice) AS numeric), 2) SalesForMonth
FROM order_details od
INNER JOIN orders o ON od.orderid = o.orderid
INNER JOIN products p ON od.productid = p.productid
WHERE EXTRACT( YEAR FROM o.orderdate) = 1997 AND EXTRACT( MONTH FROM o.orderdate) = 1
GROUP BY Month, p.productname
ORDER BY salesformonth DESC
LIMIT 1
By making 12 of these queries and changing the extract-month bit in the WHERE statement from 1-12 and UNIONing them all together, I can produce the desired result but I wondered if there was an easier way that I was missing to display the same result but only using 1 query. Interested to see what y'all can come up with.
SIDE NOTE: My initial thought is that it has something to do with subqueries because what you're effectively trying to do is display the MAX(SUM(values)) but can't actually do that since you can't nest aggregate function.
Your query gives you the top selling product for a given month, and you want the same logic for multipe months at once.
Starting from your existing and working query, a simple approach is to use WITH TIES:
SELECT DATE_TRUNC('month', o.orderdate) DateMonth,
p.productname,
ROUND(CAST(SUM(od.quantity * od.unitprice) AS numeric), 2) SalesForMonth
FROM order_details od
INNER JOIN orders o ON od.orderid = o.orderid
INNER JOIN products p ON od.productid = p.productid
WHERE o.orderdate >= DATE '1997-01-01' AND o.orderdate < DATE '1998-01-01'
GROUP BY DateMonth, p.productname
ORDER BY RANK() OVER(
PARTITION BY DATE_TRUNC('month', o.orderdate)
ORDER BY SUM(od.quantity * od.unitprice) DESC
)
FETCH FIRST ROW WITH TIES
We can also use DISTINCT ON:
SELECT DISTINCT ON (DateMonth)
DATE_TRUNC('month', o.orderdate) DateMonth,
p.productname,
ROUND(CAST(SUM(od.quantity * od.unitprice) AS numeric), 2) SalesForMonth
FROM order_details od
INNER JOIN orders o ON od.orderid = o.orderid
INNER JOIN products p ON od.productid = p.productid
WHERE o.orderdate >= DATE '1997-01-01' AND o.orderdate < DATE '1998-01-01'
GROUP BY DateMonth, p.productname
ORDER BY DateMonth, SalesForMonth DESC

SQL -percent calculation

Make a report on the sales in 2015 of the products by categories (total value and
quantity sold). Also determine what% of the value of sales
for a given category represent the sales of each of the products in the category.
My query so far:
WITH sales AS
(SELECT t1.category_name
, t2.product_name
, (t3.unit_price*t3.quantity) Total_sales
, EXTRACT (YEAR FROM order_date) Year
FROM categories t1
INNER JOIN
products t2
ON t2.category_id=t1.category_id
INNER JOIN
order_details t3
ON t3.product_id=t2.product_id
INNER JOIN
orders t4
ON t4.order_id=t3.order_id
WHERE EXTRACT (YEAR FROM order_date) = '2015'
GROUP BY t1.category_name
, t2.product_name
, (t3.unit_price*t3.quantity)
, EXTRACT (YEAR FROM order_date)
ORDER BY 1
)
SELECT s.category_name
, s.product_name
, SUM (Total_sales)
FROM sales s
GROUP BY s.category_name
, s.product_name
ORDER BY 1
How to calculate %? Thank you
I think that you want window functions - if your database, that you did not specify, supports them:
SELECT
c.category_name
p.product_name
SUM(od.unit_price * od.quantity) as total_sales
1.0 * SUM(od.unit_price * od.quantity)
/ SUM(SUM(od.unit_price * od.quantity)) OVER(PARTITION BY c.category_id)
as category_sales_ratio
FROM categories c
INNER JOIN products t2 p ON p.category_id = c.ategory_id
INNER JOIN order_details od ON od.product_id = p.product_id
INNER JOIN orders o ON o.order_id = od.order_id
WHERE o.order_date >= '2015-01-01' AND o.order_date < '2016-01-01'
GROUP BY c.category_id, c.ategory_name, p.product_id, p.product_name
ORDER BY c.category_name, p.product_name
The window sum computes the total sales for the whole category, that you can divide the sales of the current product with.
Note that I changed your query in serveral ways:
meaningful table aliases make the query easier to write, read and maintain
filtering dates without transformation is much more efficient that using date functions
there is no need for a subquery
it is always a good idea to put the relevant primary keys in the GROUP BY clause (in case two different products or categories have the same name) - on the other hand, you also had additiona uneeded columns in that clause

Find the most popular month for customers to order a certain product

I am trying to find out which month has the most orders for a certain product (Product HHYDP). This is my code so far, but each time I try to use GROUP BY and SORT BY functions related to my problem, I get an error. There are three years in the database (2006,2007,2008) and they are formatted as (YYYY-MM-DD). I am trying to find which month has the highest total order volume across the three years, quantity is irrelevant.
SELECT p.productname, o.orderdate
FROM [Sales].[Orders] as o
JOIN [Sales].[OrderDetails] as od
ON o.orderid = od.orderid
JOIN [Production].[Products] as p
ON od.productid = p.productid
WHERE p.productname like '%hhydp%'
I am using microsoft SQL management server.
You can try to use year and month with COUNT aggregate function function and add them in group by
SELECT p.productname,
year(o.orderdate) yr,
month(o.orderdate) mn,
COUNT(*) cnt
FROM [Sales].[Orders] as o
JOIN [Sales].[OrderDetails] as od
ON o.orderid = od.orderid
JOIN [Production].[Products] as p
ON od.productid = p.productid
WHERE p.productname like '%hhydp%'
GROUP BY p.productname, year(o.orderdate) ,month(o.orderdate)

sql use aggregate function that counts a unique value with group by using inner joins

I searched and found similar questions online but not my particular one, they all use where or having clause.If theres one similar to mine please link it. It's a 2 part question and I have the first one done. Thank you in advance.
Okay so heres the question, part 1
"Find by customer, the total cost and the total discounted cost for each product on the order ?".
It also asks to use inner joins to find the customer and order it a specific way. Below is the answer.
SELECT
C.companyname, O.orderid, O.orderdate, P.productname,
OD.orderid, OD.unitprice, OD.qty, OD.discount,
(OD.unitprice * OD.qty - (OD.qty * OD.discount)) AS TotalCost,
(OD.qty * OD.discount) AS TotalDiscountedCost
FROM
Sales.Customers AS C
INNER JOIN
Sales.Orders AS O ON C.custid = O.custid
INNER JOIN
Sales.OrderDetails OD ON O.orderid = OD.orderid
INNER JOIN
Production.Products as P ON OD.productid = P.productid
ORDER BY
C.companyname, O.orderdate;
Now the second question is to
follow up and resume the first one by "customer and the order date year, the total cost and the total discounted cost on the order ?". It also asks for this, "Project following columns in the select clause as.
GroupByColumns.companyname
GroupByColumns.OrderdateYear
AggregationColumns.CountNumberOfIndividualOrders
AggregationColumns.CountNumberOfProductsOrders
AggregationColumns.TotalCost
AggregationColumns.TotalDiscountedCost
Finally to order by company name and orderdateYear( which are groups). Where im stuck is how to count the specific orders of qty that equal 1 as an aggregate function in the SELECT clause. I know it has to use the aggregate function COUNT because of the GROUP BY, just don't know how to. This is what I have.
SELECT
C.companyname, YEAR(O.orderdate) AS orderyear,OD.qty,
-- Where in the count function or if theres another way do I count all the
--single orders
--COUNT(OD.qty) AS indiviualorders,
(OD.unitprice * OD.qty - (OD.qty * OD.discount)) AS TotalCost,
(OD.qty * OD.discount) AS TotalDiscountedCost
FROM
Sales.Customers AS C
INNER JOIN
Sales.Orders AS O ON C.custid = O.custid
INNER JOIN
Sales.OrderDetails OD ON O.orderid = OD.orderid
INNER JOIN
Production.Products as P ON OD.productid = P.productid
GROUP BY
C.companyname, YEAR(O.orderdate)
ORDER BY
C.companyname, O.orderdate;
You case use a case statement inside a sum
SUM(CASE WHEN <xyz> THEN 1 ELSE 0 END)
But for the count of unique orders, use SELECT(DISTINCT ) on a key that is unique in the order table
SELECT COUNT(DISTINCT O.OrderID) As DistinctOrders FROM Table

Creating an SQL query that eliminates duplicate months/year

Hello Stack Overflow community - hopefully i'm on the right track with this one, but i'm trying to write a query where a report out shows the number of orders placed by month/year. The report currently brings up all the days where i'm trying to join them all by month/year collectively. Hopefully this makes sense, i'm pretty new to this, be gentle please ;)
select distinct month(o.orderdate) 'Month',
year(o.orderdate) 'Year', sum(od.Quantity) as Orders
from OrderDetails od
join Products p
on od.ProductID = p.ProductID
join Orders o
on od.OrderID = o.OrderID
group by o.orderdate
Order by year, month asc;
You need to group by what you want to define each row. In your case, that is the year and month:
select year(orderdate) as yyyy, month(o.orderdate) as mm,
sum(od.Quantity) as Orders
from OrderDetails od join
Products p
on od.ProductID = p.ProductID join
Orders o
on od.OrderID = o.OrderID
group by year(o.orderdate), month(o.orderdate)
Order by yyyy, mm asc;
Notes:
I changed the column names to yyyy and mm so they do not conflict with the reserved words year and month.
Don't use single quotes for column aliases. This is a bad habit that will eventually cause problems in your query.
I always use as for column aliases (to help prevent missing comma mistakes), but never for table aliases.
The product table is not needed for this query.
Edit: If you want a count of orders, which your query suggests, then this might be more appropriate:
select year(o.orderdate) as yyyy, month(o.o.orderdate) as mm,
count(*) as Orders
from orders o
group by year(o.orderdate), month(o.orderdate)
Order by yyyy, mm asc;
You have to group by month and year
select distinct month(o.orderdate) 'Month',
year(o.orderdate) 'Year', sum(od.Quantity) as Orders
from OrderDetails od
join Products p
on od.ProductID = p.ProductID
join Orders o
on od.OrderID = o.OrderID
group by month(o.orderdate), year(o.orderdate)
Order by [Year],[month]