Trying to combine two different attributes into one column - sql

I am trying to write a query that shows 3 different columns. The activity class name, total revenue, and number of customers. My code below shows those columns (along with 2 different prices, student and regular). What I am trying to do is write a query that calculates revenue based on what the customer type is * the appropriate customer type (student or regular). I can't seem to be write the query to distinguish the 2 different customer types and the appropriate price into a 'revenue' column. Any help would be much appreciated!
SELECT ACTIVITY_NAME AS CLASS,
STUDENT_PRICE,
REGULAR_PRICE,
Count(CUSTOMER.CUSTOMER_TYPE) AS NUM_CUST,
Count(CUSTOMER.CUSTOMER_TYPE) * ACTIVITY.STUDENT_PRICE AS REVENUE
FROM ACTIVITY
JOIN ACTIVITY_BOOKING
ON ACTIVITY.ID = ACTIVITY_BOOKING.ACTIVITY_ID
JOIN CUSTOMER
ON ACTIVITY_BOOKING.CUSTOMER_ID = CUSTOMER.ID
GROUP BY ACTIVITY_NAME,
STUDENT_PRICE,
REGULAR_PRICE
ORDER BY ACTIVITY.ACTIVITY_NAME

I think you need SUM not COUNT and you can sum conditional value as:
SELECT ACTIVITY_NAME AS CLASS,
STUDENT_PRICE,
REGULAR_PRICE,
Count(CUSTOMER.CUSTOMER_TYPE) AS NUM_CUST,
Sum (case when CUSTOMER.CUSTOMER_TYPE = 'Student' then STUDENT_PRICE when CUSTOMER.CUSTOMER_TYPE = 'Regular' then REGULAR_PRICE else 0 end) AS REVENUE
FROM ACTIVITY
JOIN ACTIVITY_BOOKING
ON ACTIVITY.ID = ACTIVITY_BOOKING.ACTIVITY_ID
JOIN CUSTOMER
ON ACTIVITY_BOOKING.CUSTOMER_ID = CUSTOMER.ID
GROUP BY ACTIVITY_NAME,
STUDENT_PRICE,
REGULAR_PRICE
ORDER BY ACTIVITY.ACTIVITY_NAME

Related

Does it matter to filter results when doing aggregation?

I want to get my sales for each day which is located in my orders_summary table.
orders_summary table columns: id, date, amount, sku_id
products table columns: id, sku
Currently Im getting my daily sales like this:
SELECT
MAX(CASE WHEN os.date = '01/01/2022' THEN COALESCE(amount,0)::INT ELSE 0 END) AS orders_1,
MAX(CASE WHEN os.date = '01/02/2022' THEN COALESCE(amount,0)::INT ELSE 0 END) AS orders_2
FROM products AS p
LEFT JOIN orders_summary AS os ON p.id = os.sku_id
WHERE p.id = '1'
GROUP BY p.id;
Is it important to add AND date BETWEEN '01/01/2022' AND '01/02/2022' in my where clause?
Yes absolutely. Imagine having 10 years worth of data in the table where you're only interested in the data for two days. You must use the where clause which restricts the number of rows (down to 0.05% in this case) before doing the group by.

SQL Pivot column values

I have tried following this and this(SQL Server specific solution) but were not helpful.
I have two tables, Product and Sale and I want to find how many products are sold on each day. But I want to pivot the table so that columns become the products name and each row will contain the amount of products sold for each day ordered by the day.
Simplified schema is as following
CREATE TABLE product (
id integer,
name varchar(40),
price float(2)
);
CREATE TABLE sale(
id integer,
product_id integer,
transaction_time timestamp
);
This is what I want
I only managed to aggregate the total sales per day per product but I am not able to pivot the product names.
select date(sale.transaction_date)
, product.id
, product.name
, count(product_id)
from sale inner join
product on sale.product_id = product.id
group by date(sale.transaction_date)
, product.id
, product.name
This is the situation so far
Please suggest.
You need pivoting logic, e.g.
select
s.transaction_date::date,
count(case when p.name = 'intelligent_rubber_clock' then 1 end) as intelligent_rubber_clock,
count(case when p.name = 'intelligent_iron_wallet' then 1 end) as intelligent_iron_wallet,
count(case when p.name = 'practical_marble_car' then 1 end) as practical_marble_car
from sale s
inner join product p
on s.product_id = p.id
group by
s.transaction_date::date;
Since your expected output aggregates by date alone, then only the transaction date should be in your GROUP BY clause. The trick used here is to take the count of a CASE expression which returns 1 when the record is from a given product, and 0 otherwise. This generates conditional counts for each product, all in separate columns. To add more columns, just add more conditional counts.

Get Sum of quantities from multiple tables?

I have at least 8 tables from where I need to match the customer name and fetch the quantities and get the sum of all the quantities fetched from these 8 tables. I am trying to write a code which will ignore the customer whose sum of quantities is zero.
For an example lets take two tables purchase_sugar and sales_sugar I have tried a lot of queries but only this one is returning some result which is wrong.
SELECT sum(purchase_sugar.qty + sales_sugar.qty) AS Total_Amount from purchase_sugar inner join sales_sugar on purchase_sugar.supplier = sales_sugar.customer WHERE purchase_sugar.supplier = "+str(x.id)+"
The Table structures are like:
purchase_sugar have two columns supplier and qty.
And sales_sugar have structure like customer and qty.
How can I get the SUM of QUANTITIES of these tables if I provide one name and search it through these tables and get the quantities. The other thing is that I dont want the customer to be found in all the tables. If it is found in one table we should just get the quantity from that one table and for that reason I don't think that JOIN is useful or may be i am wrong.
To take care of the situation where a supplier/customer is not in all the tables, you can use union all and group by:
select name, sum(p_qty) as sum_p, sum(s_qty) as sum_s,
sum(p_qty) + sum(s_qty)
from ((select ps.supplier as name, ps.qty as p_qty, 0 as s_qty
from purchase_sugar ps
) union all
(select ss.customer as name, 0, ss.qty
from sales_sugar ss
)
) s
group by name;
Notes:
This query gets results for all names. You can use a where clause to restrict the results to one name.
You don't have to split the quantities into two (or eight) different columns, if you just want the overall sum.
You can aggregate before the union all, but that is not necessary.
you should JOIN the sum and not sum the join
select t1.purchase_sum + sales_sum as Total_Amount
from (
select purchase_sugar.supplier, sum(purchase_sugar.qty) as purchase_sum
from purchase_sugar
group by purchase_sugar.supplier
) t1
inner join (
select sales_sugar.customer, sum(sales_sugar.qty) as sales_sum
from sales_sugar
group by sales_sugar.customer
) t2 on t1.supplier = t2.customer and t1.supplier = "+str(x.id)+"

Subtract two SUM GROUP BY fields

I have two tables itemOrders and itemUsage.
itemOrders has two fields: item_number and qty_ordered
itemUsage has two fields: item_number and qty_used
I'm trying to word my SQL query so that it sums up the quantity of each item number in both tables then subtracts the totals in itemUsage from itemOrders
I've come up with this so far:
SELECT itemOrders.item_number
,(
SELECT sum(qty_ordered)
FROM itemOrders
GROUP BY itemOrders.item_number
) - (
SELECT sum(qty_used)
FROM itemUsage
GROUP BY itemUsage.item_number
) AS item_total
FROM itemOrders
INNER JOIN itemUsage
ON itemOrders.item_number = itemUsage.item_number
GROUP BY itemOrders.item_number
What happens here is that all fields come out to 0.
Example if item number "A" was showing a total quantity of 3 ordered across all instances of "A" in the itemOrders table, and only a total quantity used of 1 across all instances of "A" in the itemUsage table. The sql should show the number one in the item_total field next to 1 instance of "A" in the item_number field.
The problem is you are creating a CARTESIAN PRODUCT and repeting the values on the SUM just calculate each value separated and then LEFT JOIN both. In case no item are used COALESCE will convert NULL to 0
SELECT io_total.item_number,
order_total - COALESCE(used_total, 0) as item_total
FROM (SELECT io.item_number, sum(io.qty_ordered) as order_total
FROM itemOrders io
GROUP BY io.item_number
) io_total
LEFT JOIN (SELECT iu.item_number, sum(iu.qty_used) as used_total
FROM itemUsage iu
GROUP BY iu.item_number
) as iutotal
ON io_total.item_number = iutotal.item_number
Well it looks like you are making three queries, two separate ones, one for each sum, and one with an inner join that isn't being used.
Try
Select itemOrders.item_number, sum(itemOrders.qty_ordered - itemUsage.qty_used) as item_total
from itemOrders INNER JOIN itemUsage
On itemOrders.item_number = itemUsage.item_number
GROUP BY itemOrders.item_number

sql select sum off of two where clauses

SELECT Projects.Projectid, Projects.ProjectNumber, Projects.ProjectName,
Projects.ProjectBudgetedIS, Projects.ProjectSpentIS,
Projects.ProjectBudgetedBusiness, Projects.PorjectSpentBusiness, Project.Status,
ProjectStatus.Status AS Expr1
FROM Projects
INNER JOIN ProjectStatus ON Projects.Status = ProjectStatus.StatusID
WHERE Projects.Status = #Status
So what I want to do is take the sum of a table called invoices which has a field called ISorBusiness and a field called totalspent and store that data into the projects tabel in the appropriate field. So that when I get an invoice that is charged to the IS it takes that amount and rolls it into the Projects.ProjectSpentIS and if I get a invoice that is to the business it rolls it into the Projects.ProjectBudgetedBusiness.
I know this should be easy and sorry for the noobish question. Thanks in advance!
I would do something like:
SELECT SUM(CASE WHEN (IsOrBusiness = 'IS') THEN totalSpent ELSE 0 END) AS IsSpent,
SUM(CASE WHEN (IsOrBusiness = 'Business') THEN totalSpent ELSE 0 END) AS BusinessSpent
FROM Invoices
Obviously the usage depends on whether you are trying to write an insert query or select this data as part of the select query you have posted.