I am using SQL and here is the scenario I am stuck with
Table A
SubscriptionID | Club | Sum_Of_Billings_Of_All_Month | EventID
Table B:
Cost | EventID
Table A left join Table B on EventID (To track the cost of each subscription)
Result
SubscriptionID | Club | Sum_Of_Billings_Of_All_Month | EventID | Cost
I want to break down the Sum_Of_Billings_Of_All_Month into per day billings. i.e. for each subscription, I want the breakdown of billings per day of the month. For that I will group by Sum_Of_Billings_Of_All_Month instead of subscriptionID.
Consequence
If I group by days of billing, upon joining I will get duplicates of subscriptionIDs and the eventIDs will be duplicated in rows multiple time which will then count the cost multiple times as well.
What I want:
In the same query, I want to be able to group by SubscriptionID so I can keep the unique subscriptions per row with their cost.
But one of the other requirement is that I want to know the breakdown of the billings as well to calculate the breakeven and other metrics in the same query
Here is the actual sample data
Table A
idCustomerSubscription | ClubID | EventId | BillingDate| FinalRevenue
33562784 | 56180001| 5y6m600np1fg | 5/31/2017 | 512
Table B
EventId |Cost
5y6m600np1fg |200
Table A join B left join on eventId (Group by SubscriptionID
idCustomerSubscription |ClubID |EventId |BillingDate| FinalRevenue | Cost
33562784 | 56180001 |5y6m600np1fg| 5/31/2017 | 512 |200
It serves the purpose because each subscription has one cost which is unique BUT it on the other hand, this kind of query will not give me breakdown of dates of billings (I need it for the breakeven calculation)
Table A join B left join on eventId (Group by billingdate
idCustomerSubscription| ClubID |EventId | BillingDate| FinalRevenue |Cost
33562784 | 56180001| 5y6m600np1fg |5/30/2017 |510 |200
33562784 | 56180001| 5y6m600np1fg |5/31/2017 |2 |200
This would give me the breakdown of the dates which i need for breakeven (510 on 30th and 2 on 31st) but it will make the cost duplicated (400 is the cost instead of 200)
I want to find out a SQL magic where I can keep the number of unique subcriptions per row and some way to track the billing dates of each subscriptions in the same query (without grouping it by date because it will make the rows duplicated). Is it possible ?
Perhaps some way where when the eventids are joined and its grouped by date, it doesnt duplicate the cost and count only one cost per eventid?
I hope you will get your desired result with below query. Try to modify your group by operation for mn (alias name) table.
select mn.idCustomerSubscription,mn.ClubID,mn.EventId,mn.BillingDate,mn.FinalRevenue,sq.cost
from tableA Mn left join (select idCustomerSubscription,max(cost) cost, min(billingDate) billingDate from tableA a left join tableB b on a.eventid=b.eventid group by idCustomerSubscription) sq on mn.idCustomerSubscription=sq.idCustomerSubscription and mn.billingDate=sq.billingdate
group by mn.idCustomerSubscription,mn.ClubID,mn.EventId,mn.BillingDate
Related
I am running the following query and at first it appears to give the sub totals for customers and shows by date each customers payment amounts only if that total for all payments is greater than $90,000.
SELECT
Customername,
Date(paymentDate),
CONCAT('$', Round(SUM(amount),2)) AS 'High $ Paying Customers'
FROM Payments
JOIN Customers
On payments.customernumber = customers.customernumber
Group by customername, Date(paymentDate) WITH ROLLUP
having sum(amount)> 90000;
But upon looking at the records for Dragon Souveniers, Ltd. and Euro+ Shopping Channel is is actually showing the paydates that have amounts individually over $90000 as well as the subtotal for that customer as a rollup. For all other customers, their individual payment dates are not reported in the result set and only their sum is if it over $90000. For example Annna's Decorations as 4 payment records and none of them are over 90000 but her sum is reported as the value for the total payments in the query with the rollup. Is this the correct interpretation?
The HAVING clause work correct, It filters all records with a total no above 90000. It also does do this for totals.
When using GROUP BY .... WITH ROLLUP, you can detect the created ROLL UP lines by using the GROUPING() function.
You should add a condition in a way that the desired columns are not filtered.
Simple example:
select a, sum(a), grouping(a<3)
from (select 1 as a
union
select 2
union select 3) x
group by a<3 with rollup;
output:
+---+--------+---------------+
| a | sum(a) | grouping(a<3) |
+---+--------+---------------+
| 3 | 3 | 0 |
| 1 | 3 | 0 |
| 1 | 6 | 1 |
+---+--------+---------------+
this shows that the last line (with grouping(i<3) == 1) is a line containing totals for a<3.
I have one table of tbl_order where columns are :
id_order
username
delivery_date etc...
and other table tbl_order_foods where columns are :
id_order
id_food
food_quantity etc
Here the sample pic of tbl_order table
and tbl_order_foods table
Here i am want to select all the foods with quantity with price and unit based on delivery_date.
Ex: Suppose On 2020-04-18 there are 3 orders where foods: tomato's are ordered total 15 kg (3 orders * 5 quantity * food_min_unit_amount * unit) and so on others foods.
how i can get the foodlist of total ordered quantity based on delivery_date
The method you need is the GROUP BY keyword.
SQL grouping works on the given attributes. According to your question this would be the delivery_date. In the projection (the attributes following the SELECT keyword) you then can use attributes you state after the GROUP BY keyword and aggregation functions e.g. SUM and MAX.
Based on your question you could get the total price for all orders on the given date like this:
SELECT order.delivery_date, SUM(food.food_quantity) as amount, SUM(food.food_total_price) as revenue
FROM tbl_order as order
INNER JOIN tbl_order_foods as food ON order.id_order = food.id_order
GROUP BY order.delivery_date
This would result in a list like this:
date | amount | revenue
------------------------
05.01| 10 | 800.00
I don't know whether this is what you wish. If you also want to split it into order positions then you would GROUP BY the food_name as well and add it to the projection which then results in the SUM grouped by the orders on a given day of a given product.
SELECT order.delivery_date, food.food_name, SUM(food.food_quantity) as amount, SUM(food.food_total_price) as revenue
FROM tbl_order as order
INNER JOIN tbl_order_foods as food ON order.id_order = food.id_order
GROUP BY order.delivery_date, food.food_name
Which would result in something like this.
date | food_name | amount | revenue
-----------------------------------
05.01| Tomato | 10 | 800.00
05.01| Apple | 5 | 400.00
Check out GROUP BY with the SUM function, a good article from Tutorialspoint.com is here. The only difference is that you are performing a JOIN to create the resulting table.
SELECT DISTINCT [f.id_food], [o.delivery_date], SUM(f.food_quantity) as [delivered_sum_qty], SUM(f.food_total_price) as [sum_food_total_price]
FROM tbl_order o LEFT JOIN tbl_order_foods f
ON [o.id_order] = [f.id_order]
GROUP BY [o.delivery_date];
If you need it, a pretty clear explanation of how to use JOIN is here as well.
I am trying to calculate the stock by product a warehouse had over time. I have the information about today's stock, and also the amount of products sold and purchased by day. So, the calculation for yesterday values would be:
Yesterday_stock=Stock-yesterday_sold_quantity+yesterday_purchased_quantity. My problem is that i should save somewhere the amount of everyday's stock in order to calculate the stock of the previous day. I found that in order to do that i could use over sql clause with order by. But unfortunately, i have sql server 2008 and this is not a choice.
The tables are:
Prdamount which holds the current stock per product (StuPrdID ) and if it is blocked for some reason.
|-------------- |------------------|---------------
| StuPrdID | StuQAmount |prdBlockingReason
|---------------|------------------|-------------
| 12345| 16 |
|---------------|------------------|--------------
| 08889| 12 | expired
|---------------|------------------|------------
Table Moves which holds information about inserts and outputs of products. If MoveCase field has value equal 1 it is an output move, if it is a 2 it is a purchased quantity. Moves table dummy data:
|-------------- |--------------------- -|--------|-------
|MoveItemCode | MoveDate |MoveCase|MoveRealQty
|---------------|---------------------- |--------|-------
| 12345 |2018-06-24 00:00:00.000| 1 |14
|---------------|-----------------------|--------|--------
| 08889 |2018-06-24 00:00:00.000| 2 |578
|---------------|-----------------------|--------|--------
and table Product with information related with data:
|-------------- |------------------|
| PrdCode | PrdDespription |
|---------------|------------------|
| 12345| Orange juice|
|---------------|------------------|
| 08889| Chocolate|
|---------------|------------------|
I want an output like this:
|------------|--------------------- -|--------|--------------|------------
|Prdcode | PrdDescription |Stock |Stock 18/07/03|Stock 18/7/02
|------------|---------------------- |--------|--------------|------------
| 12345 |Orange Juice | 80 |50 34
|----------- |-----------------------|--------|--------------|------------
| 08889 |Chocolate | 45 |82 17
|------------|-----------------------|--------|--------------|-------------
this query gives me the running stock:
select
product.PrdCode,
product.PrdDescr,
SUM(StuQAmount) as Stock
from prdamount
left join product on (product.PrdID=prdamount.StuPrdID)
where prdamount.prdBlockingReason=' '
group by product.PrdCode,product.PrdDescr
order by product.PrdCode asc
This query gives me the quantity sold by product per day:
select
moves.MoveItemCode,
prd.PrdDescr,
moves.MoveDate,
SUM(MoveRealQty) as 'sold_quantity'
from moves
left join prd on (moves.MoveItemCode=product.PrdCode)
where (moves.MoveDate>'2018-06-01' and and moves.MoveCase=1)
group by moves.MoveItemCode,product.PrdDescr,moves.MoveDate
order by moves.MoveItemCode asc,moves.MoveDate asc
And this query gives me the quantity purchases by product per day:
select
moves.MoveItemCode,
prd.PrdDescr,
moves.MoveDate,
SUM(MoveRealQty) as 'Purchased_Quantity'
from Moves
left join product on (moves.MoveItemCode=product.PrdCode)
where (moves.MoveDate>'2018-06-01' and moves.MoveCase=2)
group by moves.MoveItemCode,product.PrdDescr,moves.MoveDate
order by moves.MoveItemCode asc,moves.MoveDate asc
I tried to combine these 3 queries into one using subqueries, but it didn't work. So how can i accomplish the result that i want? Sorry if the question is silly, i am a beginner in sql
try this,
select
product.PrdCode,
moves.MoveItemCode,
product.PrdDescr,
moves.MoveDate,
SUM( case when moves.MoveCase=1 then MoveRealQty else 0 end) as 'sold_quantity',
SUM( case when moves.MoveCase=2 then MoveRealQty else 0 end) as 'Purchased_Quantity',
(select SUM(StuQAmount) from prdamount where StuPrdID = product.PrdID and prdBlockingReason=' ')
from moves
left join product on (moves.MoveItemCode=product.PrdCode)
where (moves.MoveDate>'2018-06-01')
group by moves.MoveItemCode,product.PrdDescr,moves.MoveDate, product.PrdCode
order by moves.MoveItemCode asc,moves.MoveDate asc
I have three tables:
1 dates - contains column date
2 book - contains columns room, date and surname
3 people - contains column surname
I am able to get dates where there were people in rooms on certain days within the range of dates.
SELECT date, IFNULL(surname, 'ghost')
FROM book JOIN dates ON book.date=dates.date JOIN people ON people.surname=book.surname
WHERE room = 113
AND date BETWEEN '2015-01-01' AND '2015-01-07'
+------------+-----------+
| Date | Surname |
+------------+-----------+
| 2015-01-02 | Surname 1 |
| 2015-01-05 | Surname 2 |
+------------+-----------+
How do I return a full list of dates, including those where there was nobody in a room so every date from given range is printed and if no people in the specified room, then 'ghost' is printed instead?
You need to use a LEFT JOIN
SELECT dates.date, IFNULL(book.surname, 'ghost')
FROM dates
LEFT JOIN book
ON book.date=dates.date
AND book.room = 113
-- LEFT JOIN people ON people.surname=book.surname
WHERE dates.date BETWEEN '2015-01-01' AND '2015-01-07'
Note that book.room = 113 needs to be in the ON clause. Using it in the WHERE clause would convert the LEFT JOIN to INNER JOIN.
I have a table of recipes, and I want to show a weekly value for each of them. The values are votes cast for them. My problem is that I want to make an excel-like table with all available fridays on my db, add a column for each recipe, and put it's value for the friday on that column, if any value exists.
Now apparently the easiest join doesn't work so I wrote two queries: one to get all ids for my recipes and one for the values to show. The first (MySql) query is just a select id from recipes, the second is like this:
select d.date,perc from
(SELECT date FROM weekly where YEAR(date)=2014 group by date) as d
left join weekly on d.date = weekly.date and weekly.id_rec= :idrec
Any idea how to merge those two queries? Running two queries makes everything slow down, but when I tried to merge them I didn't get the correct results.
Data:
sql fiddle
The result should be something like:
Dates | Recipe A | Recipe B | ...
Date 1 | 0.005 | 0.11 |
Date 2 | 0 | 0 |
Date 3 | 0 | 0.1 |
Note that Date 2 doesn't exist for Recipe A and B, but for some other do.
You should be able to merge the two queries like this:
SELECT recipes.id, votes.date, votes.perc FROM recipes
RIGHT JOIN
(select weekly.id_rec, d.date, perc from
(SELECT weekly.id_rec, date FROM weekly where YEAR(date) = 2014 group by date) as d left join weekly on d.date = weekly.date) as votes
ON votes.id_rec = recipes.id
SQL Fiddle