mysql - 将 dplyr 转换为 sql
问题描述
我的数据结构如下:
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
这些数据代表俱乐部会员资格,目标是提取那些取消会员资格并随后重新加入的会员。特别是我对取消和重新加入之间的天数感兴趣。
在 RI 中可以做到:
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()
wheredrop_na(time_to_rejoin)
处理成员具有多个并发未取消成员资格的情况,这会导致:
# 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
我怎样才能在 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 )
解决方案
SELECT t1.id,
COALESCE(t1.cancelled, t1.end) `end`,
t2.start next_start,
DATEDIFF(t2.start, COALESCE(t1.cancelled, t1.end)) gap
FROM dat t1
JOIN dat t2 ON t1.id = t2.id
AND COALESCE(t1.cancelled, t1.end) < t2.start
WHERE NOT EXISTS ( SELECT NULL
FROM dat t3
WHERE t1.id = t3.id
AND COALESCE(t1.cancelled, t1.end) < t3.start
AND COALESCE(t3.cancelled, t3.end) < t2.start )
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=e822fab2c63812c4f815f2700e62dd7e
PS。小提琴中的错误 src 数据(错字?)已修复。
聚苯乙烯。如果您不需要返回相邻的句点,则添加HAVING gap > 1
到查询的最末尾。
你能添加一个关于它是如何工作的描述吗?——乔金
t1
t2
表格副本用于检索“上一个”和“下一个”期间。
t3
允许确保它们是相邻的(从t1
和开始的时间段之间没有任何时间段t2
)。
也就是说,如果我们有 3 个周期,那么 JOIN 会产生 3 对 (1-2)、(2-3)、(1-3),但 WHERE 会删除最后一对,因为在周期 1 和周期 3 之间存在周期 2。
COALESCE 用于获取cancelled
是否已设置和end
未设置(为 NULL)。
推荐阅读
- vue.js - 使用 sass 在基于 vue 的项目中进行主题切换
- javascript - 将输入字符串转换为数字并求和
- python - 如何使用 boto3 查找特定角色的所有受信任实体?
- c++ - 如何解决 codechef 中的 SIGEMT 运行时错误?
- compiler-optimization - 应用程序崩溃,Xcode11.4,iOS 10.3.3 10.3.4,iPhone 5c /5 iPad4 (armv7s)
- vue.js - Safari 浏览器不支持 V-carousel?
- spring - 如何在 Spring Boot 中将嵌套的 JSON 对象映射为 SQL 表行
- r - 在 data.table 中填充不完整的时间序列
- google-chrome - Web Speech API 支持哪些语言?
- gradle - ClassNotFoundException: com.sun.net.httpserver.HttpHandler- 带有 Googledrive 数据存储的 JAVAFX 应用程序