Group by dates using a different table date range - mysql

I am trying to get the sum of costs by date, if the date lies between the start and end date which is coming in from a different table.
To explain:
Table 1
id
date
cost
1
2020-02-02
$10
2
2020-03-05
$100
1
2020-03-10
$200
3
2020-07-16
$200
1
2019-01-01
$50
1
2019-02-10
$50
3
2012-10-01
$500
Table 2
id
start_date
end_date
1
2020-01-01
2020-12-31
3
2020-01-01
2020-11-15
2
2020-01-01
2021-01-31
I just want to aggregate the costs by month only if the date in table 1 lies within the start and end date of table 2. So here I want the output to look like:
date
cost
2020-01-31
$10
2020-02-29
$10
2020-03-31
$300
2020-04-30
-
2020-05-31
-
2020-06-30
-
2020-07-31
$200
2020-08-31
-
2019-09-30
-
2019-10-31
$500
2019-11-30
-
2019-12-31
-
What I have tried so far:
select sum(cost), last_day(date)
from table1 inner join table2
on table1.id=table2.id
and table1.date>=table2.start_date and table1.date<=table2.end_date
group by last_day(date)

select year(date) as year,month(date) AS month, sum(cost) AS cost
from table1 inner join table2
on table1.id=table2.id
and table1.date>=table2.start_date and table1.date<=table2.end_date
group by table1.id, year(date), month(date)
order by last_day(date)

Related

Counting club memberships in SQL

EDIT: I have added the primary key, following the comment by #Strawberry
The aim is to return the number of current members, and also the number of past memberships, on any particular date/time.
For example, suppose we have
msid id start cancelled
1 1 2020-01-01 09:00:00 null
2 2 2020-01-01 09:00:00 2020-12-31 09:00:00
3 2 2021-01-01 09:00:00 null
4 3 2020-01-01 09:00:00 2020-06-30 09:00:00
5 3 2020-02-01 09:00:00 2020-06-30 09:00:00
6 3 2020-07-01 09:00:00 null
and we want to calculate the number of members at various times, which should return as follows
Datetime Current Past <Notes - not to be returned by the query>
2020-01-01 12:00:00 3 0 -- all 3 IDs have joined earlier on this date
2020-02-01 12:00:00 3 0 -- new membership for existing member (ID 3) is not counted
2020-06-30 12:00:00 2 1 -- ID 3 has cancelled earlier on this day
2020-07-01 12:00:00 3 0 -- ID 3 has re-joined earlier on this day
2020-12-31 12:00:00 2 1 -- ID 2 has cancelled earlier on this day
2021-01-01 12:00:00 3 0 -- ID 2 has re-joined earlier on this day
An ID may either be current or past, but never both. That is, if a past member re-joins, as in the case of ID 2 and 3 above, they become current members, and are no longer past members.
Also, a member may have multiple current memberships, but they can only be counted as a current member once, as in the case of ID 3 above.
How can this be achieved in MySQL ?
Here is a db<>fiddle with the above data
Test this:
WITH
cte1 AS ( SELECT start `timestamp` FROM dt
UNION
SELECT cancelled FROM dt WHERE cancelled IS NOT NULL ),
cte2 AS ( SELECT DISTINCT id
FROM dt )
SELECT cte1.`timestamp`, COUNT(DISTINCT dt.id) current, SUM(dt.id IS NULL) past
FROM cte1
CROSS JOIN cte2
LEFT JOIN dt ON cte1.`timestamp` >= dt.start
AND (cte1.`timestamp` < dt.cancelled OR dt.cancelled IS NULL)
AND cte2.id = dt.id
GROUP BY cte1.`timestamp`
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=942e4c97951ed0929e178134ef67ce69

MySQL SUM two columns then another column with the net amount

Hi ive tried all the solution on stack over flow to no avail
i have 2 tables with a ID primary key, then date, and amount. there can be multiple dates of the same date in the table. the debits uses negative numbers in debits table
table "credits"
id | date | amount
1 2020-01-01 10.00
2 2020-01-02 20.00
3 2020-01-03 30.00
4 2020-01-01 10.00
5 2020-01-02 10.00
6 2020-01-03 10.00
table "debits"
id | date | amount
55 2020-01-01 -5.00
56 2020-01-02 -5.00
57 2020-01-03 -5.00
58 2020-01-01 -5.00
59 2020-01-02 -5.00
60 2020-01-03 -5.00
I want to return a 3 column result like so, grouped by DATE with 4 fields, date, amount credits (for teh day) amount debits (for the day) and the amont total (for the day)
date | amount_credits | amount_debits | amount_total
2020-01-01 20 10 10
2020-01-02 30 10 20
2020-01-03 40 10 30
I would do this using union all and aggrgtion:
select date, sum(credit) as credits, abs(sum(debits)) as debits),
sum(credits) + sum(debits) as net
from ((select c.date, c.amount as credit, 0 as debit
from credits c
) union all
(select c.date, 0, d.amount
from debits d
)
) cd
group by date;
I note that the sign of the debits amount changes, from the source table to the result set, which is why the outer query uses abs().
In particular, using union all and group by ensures that all dates in the original data are in the result set -- even if the date in in only one of the tables.
I'd group both tables on the date and then join the two:
SELECT c.date, amount_credits, amount_debits, amount_credits - amount_debits AS amount_total
FROM (SELECT date, SUM(amount) AS amount_credits
FROM credits
GROUP BY date) c
JOIN (SELECT date, -1 * SUM(amount) AS amount_debits
FROM debits
GROUP BY date) d ON c.date = d.date

Calculate MRR Kpi without monthly invoices

I am trying to calculate mrr for each month.
The DB table 'boxes' looks like this:
project_id
product_id
payment_method_id
price
interval
booked_at
canceled_at
1
1
3
19.00
1
2020-12-01 00:00:00
NULL
1
2
3
39.00
1
2020-05-01 00:00:00
2020-11-05 19:10:27
4
1
3
39.00
12
2020-05-01 00:00:00
2020-11-05 19:10:27
Payment-Interval is in months. I need to show in KPI dashboard the mrr.
Currently I have this query:
SELECT DATE_FORMAT(booked_at, '%Y-%m') AS period, sum(price)
FROM
project_boxes
GROUP BY period;
The problem with the above query is that it doesn't show between months MRR and doesn't work with canceled boxes.
What am I missing? Any help is appreciated.

joining two database tables in mysql and laravel

I have these two tables.
as_tbl_company_holidays
id year company_id start_date, end_date, description
1 2020 1 2020-01-01 2020-01-01 New Year Holiday
2 2020 1 2020-02-14 2020-02-15 Valentine Holiday
3 2020 2 2020-01-01 2020-01-01 New Year Holiday
as_tbl_employee_holidays
id employee_id company_id year start_date end_date description
1 ASL100 1 2020-01-31 2020-01-31 Casual Holiday
2 ASL200 2 2020-04-01 2020-04-02 Easter Holiday
How can i join these two table to get a holiday data for a particular employee i.e.
id employee_id company_id year start_date end_date description
1 ASL100 1 2020 2020-01-01 2020-01-01 New Year Holiday
2 ASL100 1 2020 2020-02-14 2020-02-15 Valentine Holiday
3 ASL100 1 2020-01-31 2020-01-31 Casual Holiday
id employee_id company_id year start_date end_date description
1 ASL200 2 2020 2 2020-01-01 2020-01-01 New Year Holiday
2 ASL200 2 2020 2 2020-04-01 2020-04-02 Easter Holiday
Meanwhile, I wrote this SQL query and it's returning duplicate data. How can I combine the data from both tables into one.
select
emp.employee_id,
comp.company_id,
comp.year,
comp.start_date,
comp.end_date
from
as_tbl_company_holidays as comp
left join as_tbl_employee_holidays as emp on comp.company_id = emp.company_id
where
emp.employee_id = "ASL100" and
comp.company_id = 1
I guess you need a union query instead of join
select company_id,year, start_date, end_date,description
from as_tbl_company_holidays
where company_id = 1
union
select company_id,year, start_date, end_date ,description
from as_tbl_employee_holidays
where company_id = 1
and employee_id = "ASL100"

how can i summarize some data in a MySQL table based on subsets of data determined by a datetime field?

Lets say i have this table:
id name date qty
1 bananas 2020-04-01 00:00:00 20
2 apples 2020-04-02 00:00:00 15
3 apples 2020-04-05 00:00:00 15
4 bananas 2020-04-06 00:00:00 10
5 bananas 2020-04-15 00:00:00 40
6 bananas 2020-04-16 00:00:00 20
7 apples 2020-04-17 00:00:00 15
8 apples 2020-04-17 00:00:00 5
What i want to achieve is a result set with total quantity of each fruit before 2020-04-06 in a InitialStock field and total quantity of each fruit after 2020-04-17 as FinalStock
It looks like you want conditional aggregation:
select
name,
sum(case when date <= '2020-04-06' then qty end) initial_stock,
sum(case when date >= '2020-04-17' then qty end) final_stock
from mytable
group by name
For each name, this gives you the sum of qty before April 4th and after Apri 17th, in two separated columns.