Get all rows that overlaps dates - mysql

Question
I have a table that holds all the work experience of each employee. I want to get all work experience of employee that overlapped the dates. Below is the sample.
Scenario
Employee 1 have a total of two (2) work experience.
Employee 2 have a total of three (3) work experience.
tbl_work_exp
employee_id
start_date
end_date
1
2021-01-01
2021-06-30
1
2021-07-01
2021-12-31
2
2021-01-01
2022-02-01
2
2021-07-01
2021-12-31
2
2022-01-01
present
3
---
---
4
---
---
5
---
---
and so on...
The first row of Employee 2 overlap the dates to its present work experience.
What I need is to get all rows that overlap the dates, like the table below.
Results
employee_id
start_date
end_date
2
2021-01-01
2022-02-01
2
2021-07-01
2021-12-31
2
2022-01-01
present
Thank you in advance.

Related

Mysql / Big Query to Find when a customer loses access for the first time (Gap / Island)

I'm hoping the query will work both in Mysql and BigQuery
For each customer I need to find the first date they had a subscription and the first date that they stopped having any subscriptions (e.g. a break in subscription). A customer can have multiple overlapping subscriptions. Once a customer stops having access then future subscriptions are not considered.
This is a sample table with a few rows. The actual table will have millions of rows and thousands of customers.
using this sample data:
select * from test_sub order by customer_id, effect_date, expire_date;
subscription_id
customer_id
effect_date
expire_date
1
1
2022-01-01 00:00:00
2022-03-01 00:00:00
2
2
2021-01-01 00:00:00
2021-03-01 00:00:00
3
2
2021-02-01 00:00:00
2021-04-25 00:00:00
4
2
2021-05-01 00:00:00
2021-06-01 00:00:00
5
2
2021-08-01 00:00:00
2022-10-01 00:00:00
The answer should be:
customer_id
min(effect_date)
max(expire_date)
1
2022-01-01 00:00:00
2022-03-01 00:00:00
2
2021-01-01 00:00:00
2022-04-25 00:00:00

Calculate Employee Experience from Multiple Jobs

I have a table named employee experience with id, userId, startDate, endDate columns.
I want to calculate employee experience. Can someone please help with mysql query or JPA specification code?
For example in case of following data:
id
userID
startDate
endDate
1
1
2021-01-01
2022-01-01
2
2
2019-01-01
2020-01-01
3
2
2020-01-02
2021-01-01
4
3
2021-01-01
2022-01-01
the output should be:
userID
experience
1
1
2
2
3
1
Successfully did this with the following:
SELECT SUM(TIMESTAMPDIFF(YEAR, START_DATE, END_DATE)) AS experience,
SOCIAL_PROFILE_ID
FROM tableName
GROUP BY SOCIAL_PROFILE_ID

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

Best way to join tables with ranges of dates

I have a very simple question but i can't find a good solution.
Table A:
ID_A DateStart DateEnd no_days
1 2019-02-01 2019-02-04 3
2 2019-02-04 2019-02-06 2
Table B:
ID_B ID_A Date DaysToDate
1 1 2019-02-01 10
2 1 2019-02-02 9
3 1 2019-02-03 8
4 2 2019-02-04 7
5 2 2019-02-05 6
So i'm starting with Table A and after having created one record, i create N rows for Table B.
In my project i'll then need to do the join
select * from TableA join TableB using(ID_A)
in order to have all the days listed, with their own "days to this date" value. I need the join because my user could be searching for a range of days and i need to know how many rows of TableB are involved in this search.
This is all good, it works really fast but the database is growing A LOT and i'm sure there has to be a more intelligent way to solve this problem, maybe with a static "Days" table simply listing one row per day in for the next 100 years...but i can't find a working solution because i need to keep speed and the "days to date" value.
The results i need are of this kind
select * from TableA join TableB using(ID_A) where DateStart between '2019-02-01' and '2019-02-05'
ID_A DateStart DateEnd no_days ID_B Date DaysToDate
1 2019-02-01 2019-02-04 3 1 1 2019-02-01 10
1 2019-02-01 2019-02-04 3 2 1 2019-02-02 9
1 2019-02-01 2019-02-04 3 3 1 2019-02-03 8
2 2019-02-04 2019-02-06 2 4 2 2019-02-04 7
Do you have any hints?

SQL joining on two columns with a variation on the first column

I have two tables:
Table 1: planA
ID Date Count
3 2017-01-01 10
2 2017-02-03 15
10 2017-01-30 8
Table 2: planB
ID Date Value
3 2017-01-02 11
2 2017-02-04 12
21 2017-01-30 3
3 2017-02-03 33
What I want to do is to join the two tables on (ID and Date) columns.
However, on Date, I want to use the next day to the date on the table 1.
Therefore, the joined table should look like the following:
PlanA.ID PlanA.Date PlanB.Date PlanA.Count PlanB.Value
3 2017-01-01 2017-01-02 10 11
2 2017-02-03 2017-02-04 15 12
Is this even possible?
Any suggestion would be appreciated!
Yes it is possible:
select
PlanA.ID,
PlanA.Date,
PlanB.Date,
PlanA.Count,
PlanB.Value
from
PlanA inner join PlanB
on (
PlanA.ID = PlanB.ID
and
PlanA.Date + INTERVAL 1 DAY = PlanB.Date
)
if Date is a column of type date, + INTERVAL 1 DAY will return the next day of the one given, and then you can perform the join.