I have data structured as follows:
id start end cancelled
1 2020-01-01 2020-12-31 2021-01-10
1 2021-02-01 2022-01-31 NA
2 2020-01-01 2020-12-31 NA
3 2020-01-01 2020-06-30 2020-07-01
3 2020-07-10 2021-01-09 2021-01-31
3 2021-02-02 2021-08-01 NA
These data represent club memberships and the goal is to extract those members who cancel their membership and later re-join. In particular I am interested in the number of days between cancellation and re-joining.
In R I can do:
dat <- structure(list(id = c(1, 1, 2, 3, 3, 3), start = c("2020-01-01",
"2021-02-01", "2020-01-01", "2020-01-01", "2020-07-10", "2021-02-02"
), end = c("2020-12-31", "2022-01-31", "2020-12-31", "2020-06-30",
"2021-01-09", "2021-08-01"), cancelled = c("2021-01-10", NA,
NA, "2020-07-01", "2021-01-31", NA)), class = "data.frame", row.names = c(NA,
-6L)) %>%
dat[,-1] <- lapply(dat[,-1], as.Date)
dat %>%
group_by(id) %>%
summarize(
rejoin_date = start[-1],
time_to_rejoin = as.numeric(start[-1] - cancelled[-n()], units="days")
) %>% drop_na(time_to_rejoin) %>%
ungroup()
where drop_na(time_to_rejoin) handles the cases where a member has multiple concurrent uncancelled memberships, which results in:
# A tibble: 3 x 3
id rejoin_date time_to_rejoin
1 2021-02-01 22
3 2020-07-10 9
3 2021-02-02 2
How can I do this in MySQL ?
CREATE TABLE IF NOT EXISTS `dat` (
`id` int(6) unsigned NOT NULL,
`start` TIMESTAMP,
`end` TIMESTAMP,
`cancelled` TIMESTAMP NULL
) DEFAULT CHARSET=utf8;
INSERT INTO `dt` (`id`, `start`, `end`, `cancelled`) VALUES
('1', '2020-01-01', '2020-12-31', '2021-01-10'),
('2', '2021-02-01', '2022-01-31', NULL ),
('2', '2021-01-01', '2020-12-31', NULL ),
('3', '2020-01-01', '2020-06-30', '2020-07-01'),
('3', '2020-07-10', '2021-01-09', '2021-01-31'),
('3', '2021-02-02', '2021-08-01', NULL )