Reputation: 5984
I have basically have two tables:
1) billingcharges : here we store id of a restaurant (restid) , charge id (chargeid), chargetime(timeinmillis when the charge occurred),chargeamount(int amount of the actual charge).charge id is a foreign key to the billingchargedetails table.
2) billingchargedetails: here we store the details of all the possible charges. chargeid(primary key int), chargename (name of the charge), perdaycost (cost per day of the charge)
What i expect:
a summary report of totalamount of charge for each charge for each restaurant.
The current entries inside the tables are:
select * from billingcharges;
+--------+----------+---------------+--------------+
| restid | chargeid | chargetime | chargeamount |
+--------+----------+---------------+--------------+
| 1 | 1 | 1536363636363 | 700 |
| 2 | 1 | 1536363636363 | 500 |
| 1 | 1 | 1568789654123 | 500 |
+--------+----------+---------------+--------------+
select * from billingchargedetails;
+----------+--------------------+------------------+
| chargeid | chargename | chargecostperday |
+----------+--------------------+------------------+
| 1 | Base Charge | 50 |
| 2 | Spotlight Listing | 50 |
| 3 | Gold Notification | 500 |
| 4 | Discount (FIRST50) | 18 |
+----------+--------------------+------------------+
A simple join on chargeid ended up not giving me the qty and sum as expected.so i need some form of a left or right outer join, that much i know and tried
I tried a left join as follows:
select restid, B.chargeid, chargename, count(B.chargeid) as qty,
sum(ifnull(chargeamount,0)) as total
from billingcharges as B
left join billingchargedetails as C on B.chargeid=C.chargeid
group by restid,B.chargeid;
+--------+----------+-------------+-----+-------+
| restid | chargeid | chargename | qty | total |
+--------+----------+-------------+-----+-------+
| 1 | 1 | Base Charge | 2 | 1200 |
| 2 | 1 | Base Charge | 1 | 500 |
+--------+----------+-------------+-----+-------+
This does work and sums things but there are missing charges for each restaurant. even if they arent present inside the billinghcarges ie the left table, i need it with qty 0 and total 0.
I tried a right join and a random value was selected by mysql from the non existing entries inside the left table as follows:
select restid, B.chargeid, chargename, count(B.chargeid) as qty,
sum(ifnull(chargeamount,0)) as total
from billingcharges as B
right join billingchargedetails as C on B.chargeid=C.chargeid
group by restid,B.chargeid;
+--------+----------+-------------------+-----+-------+
| restid | chargeid | chargename | qty | total |
+--------+----------+-------------------+-----+-------+
| NULL | NULL | Spotlight Listing | 0 | 0 |
| 1 | 1 | Base Charge | 2 | 1200 |
| 2 | 1 | Base Charge | 1 | 500 |
+--------+----------+-------------------+-----+-------+
The expected output is something like:
restid chargeid chargename qty totalamount
1 1 Base Charge 2 1200
1 2 Spotlight 0 0
1 3 Gold 0 0
1 4 Discount 0 0
2 1 Base Charge 1 500
2 2 Spotlight 0 0
2 3 Gold 0 0
2 4 Discount 0 0
'same as above expected for each restid in billingcharges'
Upvotes: 0
Views: 47
Reputation: 562981
Before you can do the outer join, you need to generate the cross-product of restaurants to charge types.
Something like the following (but I have not tested it):
SELECT R.restid, D.chargename, COUNT(B.chargeid) AS qty,
SUM(IFNULL(B.chargeamount, 0)) AS total
FROM (SELECT DISTINCT restid FROM billingcharges) AS R
CROSS JOIN billingchargedetails AS D
LEFT JOIN billingcharges AS B ON R.restid=B.restid AND D.chargeid=B.chargeid
GROUP BY R.restid, D.chargename;
In this example, the cross-product of R and D is every restaurant crossed with every charge type.
Of course not all of those charges exist for every restaurant. So the outer join to billingcharges finds those rows that do exist for each respective combination of restaurant & charge type.
Upvotes: 1