SUB TOTAL WITH MULTIPLE TABLE - sql

I want to show the subtotals of each product name and maybe the commands I made are useless,
is there any suggestions for me
I have 3 tables
select
ORDERS.ORDER_NUM,
PRODUCT.PRODUCT_ID,
PRODUCT.PRODUCT_NAME,
ORDER_DETAILS.QUANTITY,
ORDER_DETAILS.UNIT_PRICE,
sum(ORDER_DETAILS.UNIT_PRICE) as SUBTOTAL
from
ORDER_DETAILS
inner join ORDERS on ORDER_DETAILS.ORDER_NUM = ORDERS.ORDER_NUM
inner join PRODUCT on ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID
group by
ORDER_DETAILS.ITEM_NUM
order by
PRODUCT.PRODUCT_NAME;
+-----------+------------+--------------+----------+------------+----------+
| ORDER_NUM | PRODUCT_ID | PRODUCT_NAME | QUANTITY | UNIT_PRICE | SUBTOTAL |
+-----------+------------+--------------+----------+------------+----------+
| 3004 | 2001 | BEER | 10 | 160,000 | 160 |
| 3012 | 2001 | BEER | 5 | 160,000 | 160 |
| 3002 | 2005 | CAKE | 5 | 50,000 | 50 |
| 3001 | 2004 | CIGARETTE | 2 | 25,000 | 25 |
| 3011 | 2004 | CIGARETTE | 5 | 25,000 | 25 |
| 3005 | 2007 | ICE CREAM | 50 | 10,000 | 10 |
| 3007 | 2010 | MILK | 3 | 45,000 | 45 |
| 3010 | 2010 | MILK | 7 | 12,000 | 12 |
| 3008 | 2008 | NOODLES | 1 | 5,000 | 5 |
| 3013 | 2006 | SODA | 50 | 12,000 | 12 |
| 3009 | 2002 | WINE | 1 | 200,000 | 200 |
| 3003 | 2002 | WINE | 2 | 200,000 | 200 |
| 3006 | 2002 | WINE | 1 | 200,000 | 200 |
+-----------+------------+--------------+----------+------------+----------+

You don't specify the database. However, you need to fix your query:
Details from the order and order line are not appropriate, if you are summarizing by product.
The SELECT and GROUP BY lists should be consistent.
The total you want is probably the price times the quantity.
So, the query should be more like this:
select p.PRODUCT_ID, p.PRODUCT_NAME,
sum(od.UNIT_PRICE * od.QUANTITY) as SUBTOTAL
from ORDER_DETAILS od join
ORDERS o
on od.ORDER_NUM = o.ORDER_NUM join
PRODUCT p
on od.PRODUCT_ID = p.PRODUCT_ID
group by p.PRODUCT_ID, p.PRODUCT_NAME
order by p.PRODUCT_NAME;
Also note the use of table aliases, so the query is easier to write and to read.

Related

how to sum a column of a queried table in sql

I have this table from a query and I would like to find the sum of the Total Cost (after discount). I have searched for a solution but I can't seem to find the one I'm looking for.
Here are the sample data from my tables
Booking
+-----------+-------------+----------+------------+
| vehicleNo |  bookingDay | driverNo | acc_status |
+-----------+-------------+----------+------------+
| 10 | 13/06/2021 | 2 | B |
| 10 | 14/06/2021 | 0 | B |
| 10 | 15/06/2021 | 2 | B |
| 20 | 17/06/2021 | 2 | B |
+-----------+-------------+----------+------------+
Vehicle
+-----------+-------------+----------------+------+
| vehicleNo |  vehicleReg | make_model | cost |
+-----------+-------------+----------------+------+
| 10 | IN10NGT | Nissan R34 GTR | 90 |
| 20 | IN10MRX | Mazda RX7 | 70 |
| 30 | IN10TSU | Toyota Supra | 80 |
+-----------+-------------+----------------+------+
Here is the query
SELECT IF(COUNT(Vehicle.vehicleNo) > 1, ROUND(Vehicle.cost,1) * ROUND(COUNT(Vehicle.vehicleNo) * 0.9,1), Vehicle.cost * ROUND(COUNT(Vehicle.vehicleNo),1)) AS 'Total after discount'
FROM Booking
INNER JOIN Vehicle
ON Vehicle.vehicleNo = Booking.vehicleNo
WHERE Booking.driverNo = 2
GROUP BY Vehicle.vehicleNo
ORDER BY Vehicle.vehicleNo;
an here is the result
+----------------------+
| Total after discount |
+----------------------+
| 162 |
| 70 |
+----------------------+
and I am expecting to have a table after calculating the sum like this
+----------------------+
| Overall cost |
|after discount |
+----------------------+
| 232 |
+----------------------+
any help is much appreciated.
i have figured it out. i used this query:
SELECT SUM(Cost) FROM (SELECT IF(COUNT(Vehicle.vehicleNo) > 1, ROUND(Vehicle.cost,1) * ROUND(COUNT(Vehicle.vehicleNo) * 0.9,1), Vehicle.cost * ROUND(COUNT(Vehicle.vehicleNo),1)) AS Cost
FROM Vehicle INNER JOIN Booking
ON Vehicle.vehicleNo = Booking.vehicleNo AND Booking.driverNo = 2
GROUP BY Vehicle.vehicleNo) AS x;

BigQuery / SQL aggregate data from one field, many records

I have the following tables:
rooms
+--------+------------+
| room_id| room_name |
+--------+------------+
| 1 | Kitchen |
| 2 | Bedroom |
+--------+------------+
room_products
+--------+------------+
| room_id| product_id |
+--------+------------+
| 1 | 101 |
| 1 | 102 |
| 1 | 103 |
| 1 | 104 |
| 2 | 105 |
| 2 | 106 |
| 2 | 107 |
+--------+------------+
products
+------------+--------------+
| product_id | product_name |
+------------+--------------+
| 101 | Kettle |
| 102 | Toaster |
| 103 | Microwave |
| 104 | Cooker |
| 105 | Bed |
| 106 | Lamp |
| 107 | Clock |
+------------+--------------+
The output I'm trying to get is:
+----------+-------------------------------------+
| room_name| product_name_aggregated |
+----------+-------------------------------------+
| Kitchen | Kettle, Toaster, Microwave, Cooker |
| Bedroom | Bed, Lamp, Clock |
+----------+-------------------------------------+
The code I have so far is:
SELECT r.room_name, STRING_AGG(p.product_name)
FROM rooms r
JOIN room_products rp ON rp.room_id = r.room_id
JOIN products p ON p.product_id = rp.product_id
WHERE r.room_id = 1 OR r.room_id = 2;
Think I'm getting all kinds of confused. Would really appreciate any help... Thank you.
You are almost there:
SELECT r.room_name, STRING_AGG(p.product_name, ',')
FROM rooms r JOIN
room_products rp
ON rp.room_id = r.room_id JOIN
products p
ON p.product_id = rp.product_id
WHERE r.room_id IN (1, 2)
GROUP BY r.room_name;
The changes are:
Added a second argument to STRING_AGG().
Changed the WHERE to use IN (more convenient; OR also works).
Added GROUP BY.
Note that I would recommend ARRAY_AGG() rather than STRING_AGG() -- arrays are quite useful in BigQuery.

How do I compute an aggregate calculation on similar sql elements in a table?

I am having a problem with generating the SQL task I want.
My goal is to have a margin calculation per each item category. The code works, but in some cases, an item might have four different costs, so when I execute the query, I get four lines with each of them the margin calculation. I would like to have one that summarizes everything.
How can I do it? I tried removing the cost from the selection at the beginning and group by at the end, but I get an error saying that it is not a valid group by expression.
If possible, I would like to know how I could compute the margin for all the entries in the table, regardless of their cost and price.
SELECT
pc.product_description,
round(li.price,2) as price,
round(li.cost_price,2) as cost_price,
SUM(li.quantity) as Total_Items_sold,
round(SUM(li.quantity)*li.price-SUM(li.quantity)*li.cost_price,2) as Gross_Margin_$,
FROM
product_description as pc
LEFT JOIN orders as li ON
pc.product_id = li.SKU
WHERE
pc.product_description = 'Sweater' and
li.state = 'complete' and
li.created_at like '2019%'
GROUP BY
pc.product_description,
li.price,
li.cost_price
Creating some dummy data for your scenario:
create table product_description
(
product_id varchar(10),
product_description varchar(50)
)
create table orders
(
SKU varchar(10),
price decimal(10,2),
cost_price decimal(10,2),
quantity int,
[state] varchar(10),
created_at varchar(20) -- Ugly, but you're treating this as a string in your query
)
insert into product_description
values
('PRO001', 'Sweater'),
('PRO002', 'Jeans'),
('PRO003', 'Shoes'),
('PRO004', 'Dress'),
('PRO005', 'Blouse')
insert into orders
values
('PRO001',29.99,13.50,3,'complete','2019-11-19'),
('PRO001',26.99,12.50,1,'complete','2018-06-18'),
('PRO004',37.99,20.75,2,'complete','2019-11-17'),
('PRO003',19.99,6.50,10,'complete','2019-11-16'),
('PRO003',19.99,6.25,5,'complete','2019-11-15'),
('PRO002',23.99,10.50,13,'complete','2019-11-14'),
('PRO004',37.99,21.00,3,'complete','2019-11-13'),
('PRO001',29.99,13.50,7,'incomplete','2019-11-12'),
('PRO003',18.99,5.50,9,'complete','2019-11-11'),
('PRO004',39.99,23.50,18,'complete','2019-11-11'),
('PRO005',19.99,11.50,23,'complete','2019-11-10'),
('PRO001',29.99,13.50,12,'complete','2019-11-09')
Resulting in the following data in these tables:
select * from product_description
/----------------------------------\
| product_id | product_description |
|------------|---------------------|
| PRO001 | Sweater |
| PRO002 | Jeans |
| PRO003 | Shoes |
| PRO004 | Dress |
| PRO005 | Blouse |
\----------------------------------/
select * from orders
/------------------------------------------------------------------\
| SKU | price | cost_price | quantity | state | created_at |
|--------|-------|------------|----------|------------|------------|
| PRO001 | 29.99 | 13.50 | 3 | complete | 2019-11-19 |
| PRO001 | 26.99 | 12.50 | 1 | complete | 2018-06-18 |
| PRO004 | 37.99 | 20.75 | 2 | complete | 2019-11-17 |
| PRO003 | 19.99 | 6.50 | 10 | complete | 2019-11-16 |
| PRO003 | 19.99 | 6.25 | 5 | complete | 2019-11-15 |
| PRO002 | 23.99 | 10.50 | 13 | complete | 2019-11-14 |
| PRO004 | 37.99 | 21.00 | 3 | complete | 2019-11-13 |
| PRO001 | 29.99 | 13.50 | 7 | incomplete | 2019-11-12 |
| PRO003 | 18.99 | 5.50 | 9 | complete | 2019-11-11 |
| PRO004 | 39.99 | 23.50 | 18 | complete | 2019-11-11 |
| PRO005 | 19.99 | 11.50 | 23 | complete | 2019-11-10 |
| PRO001 | 29.99 | 13.50 | 12 | complete | 2019-11-09 |
\------------------------------------------------------------------/
The following query gives you what you want, I believe:
select
pd.product_description as Product,
sum((o.quantity * o.price) - (o.quantity * o.cost_price)) as GrossMargin
from orders o
left join product_description pd on o.SKU = pd.product_id
group by pd.product_description
Results:
/-----------------------\
| Product | GrossMargin |
|---------|-------------|
| Blouse | 195.27 |
| Dress | 382.27 |
| Jeans | 175.37 |
| Shoes | 325.01 |
| Sweater | 377.27 |
\-----------------------/
If you then want to further filter the results on a specific year or product, you can:
select
pd.product_description as Product,
sum((o.quantity * o.price) - (o.quantity * o.cost_price)) as GrossMargin
from orders o
left join product_description pd on o.SKU = pd.product_id
where o.created_at like '2019%'
and pd.product_description = 'Sweater'
group by pd.product_description
Which you'll see, excludes the order from 2018:
/-----------------------\
| Product | GrossMargin |
|---------|-------------|
| Sweater | 362.78 |
\-----------------------/

SQL: Getting current dates price of a product and product code

I have 3 tables and I need to get a listing of product codes and their current prices.
Product table has the product name (string) and it's code (integer), Manufacturer table has the product name (string) and manufacturers code (integer) for it and the Pricing table has the manufacturers code (integer) for the products, price (numeric) and a date (date).
I don't have much experience with SQL beyond the basics and I can't really figure out how to get the proper listing.
I just built you a example in case you need it to learn :)
Product
+----+----------------+
| id | name |
+----+----------------+
| 1 | GFORCE TITAN |
| 2 | GFORCE 770 |
| 3 | GFORCE 1060 TI |
+----+----------------+
Manufacturer
+----+----------+
| id | name |
+----+----------+
| 1 | Gigabyte |
| 2 | Asus |
| 3 | MSI |
+----+----------+
Prices
+----+-------+-----------------+------------+
| id | price | manufacturer_id | product_id |
+----+-------+-----------------+------------+
| 1 | 1000 | 1 | 1 |
| 2 | 600 | 1 | 2 |
| 3 | 400 | 2 | 2 |
| 4 | 300 | 3 | 3 |
+----+-------+-----------------+------------+
And you should query something like this:
SELECT p.price, m.name as manufacturer, pr.name as product
FROM Prices p
JOIN Manufacturer m ON p.manufacturer_id = m.id
JOIN Product pr ON p.product_id = pr.id
ORDER BY p.price DESC
Result would be:
+----+-------+--------------+----------------+
| id | price | manufacturer | product |
+----+-------+--------------+----------------+
| 1 | 1000 | Gigabyte | GFORCE TITAN |
| 2 | 600 | Gigabyte | GFORCE 770 |
| 3 | 400 | Asus | GFORCE 770 |
| 4 | 300 | MSI | GFORCE 1060 TI |
+----+-------+--------------+----------------+

Calculate percentage of revenue per month

I have the following underlying data:
+-------+-------+---------------+
| Order | Month | sqft produced |
+-------+-------+---------------+
| 1001 | 4 | 10.29 |
| 1001 | 6 | 4'367.66 |
| 1001 | 7 | 203.57 |
| 1001 | 8 | 294.61 |
| 1001 | 9 | 92.28 |
| 1001 | 10 | 34.47 |
| 1001 | 12 | 16.59 |
| 1002 | 1 | 1.74 |
| 1002 | 4 | 19.54 |
| 1002 | 7 | 5'552.21 |
| 1002 | 9 | 309.62 |
| 1002 | 10 | 24.15 |
| 1002 | 12 | 52.16 |
| 1003 | 5 | 807.45 |
+-------+-------+---------------+
Those are three orders and I want to split the revenue according to the percentage of sqft produced in each month.
The revenue table:
+-------+-----------+
| Order | Revenue |
+-------+-----------+
| 1001 | 1'135'465 |
| 1002 | 1'773'499 |
| 1003 | 172'633 |
+-------+-----------+
So the output of the query should look like this:
+-------+-------+------------------+
| Order | Month | Revenue produced |
+-------+-------+------------------+
| 1001 | 4 | 2'327.72 |
| 1001 | 6 | 988'017.67 |
| 1001 | 7 | 46'050.00 |
| 1001 | 8 | 66'644.36 |
| 1001 | 9 | 20'874.86 |
| 1001 | 10 | 7'797.53 |
| 1001 | 12 | 3'752.86 |
| 1002 | 1 | 517.82 |
| 1002 | 4 | 5'815.02 |
| 1002 | 7 | 1'652'314.97 |
| 1002 | 9 | 92'141.64 |
| 1002 | 10 | 7'186.94 |
| 1002 | 12 | 15'522.60 |
| 1003 | 5 | 172'633.00 |
+-------+-------+------------------+
I am struggling with a way of getting the underlying data in that format because I can't seem to be able to split it by month.
Getting the percentage via dividing the square footage over the sum of the square footage partitioned over the [Order] would get you what you are looking for:
select p.[Order],
[Month],
Revenue,
[sqft produced],
CAST([sqft produced] / SUM([sqft produced]) OVER(PARTITION BY p.[Order]) AS DECIMAL(10,5)) * 100 as sqft_percentage,
Revenue * CAST([sqft produced] / SUM([sqft produced]) OVER(PARTITION BY p.[Order]) AS DECIMAL(10,5)) as revenue_produced
FROM [Orders] p
INNER JOIN Revenue r
ON r.[Order] = p.[Order]
Let's call the first table sqft and the second revenues. To avoid reserved words, the first table column's names will be:
order_id, month_num, sqft_produced
The second:
order_id, total_revenue
The SQL for what you need goes something like this (this is for Oracle):
SELECT order_id, month_num, (sqft_produced / total_sqft * total_revenue) revenue_produced
FROM sqft INNER JOIN
(SELECT order_id, total_sqft, total_revenue FROM (
(SELECT order_id, sum(sqft_produced) total_sqft
GROUP BY order_id) sqfts INNER JOIN revenues ON sqfts.order_id = revenues.order_id)) totals
ON sqft.order_id = totals.order_id;
Step by step:
SELECT order_id, sum(sqft_produced) total_sqft
GROUP BY order_id;
This gets you total square feet produced by order.
(SELECT order_id, sum(sqft_produced) total_sqft
GROUP BY order_id) sqfts INNER JOIN revenues ON sqfts.order_id = revenues.order_id;
This gets you a table with total revenues and total square feet.
And then you join this table to your sqft table and divide the square feet produced each month by total square feet and multiply by total revenue, thus splitting the revenue proportionally to square feet.