【发布时间】:2020-01-18 20:22:06
【问题描述】:
我有 house_leases 和 house_lease_terms(请参阅下面的表格架构)。 house_lease 可以有多个 house_lease_terms,但一次只能有一个“有效”条款。
表定义:
CREATE TABLE `house_leases` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`house_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `house_lease_terms` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`house_lease_id` int(10) unsigned NOT NULL,
`date_start` datetime NOT NULL,
`date_end` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `house_lease_terms_house_lease_id_foreign` (`house_lease_id`),
CONSTRAINT `house_lease_terms_house_lease_id_foreign` FOREIGN KEY (`house_lease_id`) REFERENCES `house_leases` (`id`) ON DELETE CASCADE
);
如您所见,house_lease_terms.house_lease_id 对应于特定的 house_lease,但是可以有多个具有相同 的行house_lease_id。
确定“活跃”术语的规则是:
date_start NOW() OR date_end 为空
如果没有返回任何行,则“活动”术语必须在将来,因此规则更改为:
date_start > NOW()
如果条款不在未来,我们按 date_start DESC 排序,因为可能会返回多行,我们希望最新的 date_start 位于结果的顶部。否则,我们按 date_start ASC 排序,因为我们希望离现在最近的 date_start 位于顶部。
然后我限制为 1 以仅获得一个结果,并且该行被视为“活动”术语。如果没有返回结果,则没有“有效”字词。
我有一个 SQL 语句,它具有获取特定 house_lease_id 的逻辑。看起来像这样:
SELECT * FROM house_lease_terms
WHERE
CASE
WHEN
(SELECT COUNT(*) FROM house_lease_terms WHERE date_start <= NOW() AND (date_end > NOW() OR date_end IS NULL) AND house_lease_id = 1)
THEN
date_start <= NOW() AND (date_end > NOW() OR date_end IS NULL)
ELSE
date_start > NOW()
END
AND house_lease_id = 1
ORDER BY
IF(
(SELECT COUNT(*) FROM house_lease_terms WHERE date_start <= NOW() AND (date_end > NOW() OR date_end IS NULL) AND house_lease_id = 1),
unix_timestamp(date_start),
-unix_timestamp(date_start)
) DESC
LIMIT 1;
此语句有效,但我希望有更好的方法(更有效)来获取特定 house_lease_id 的“有效”条款(如果您知道更好的解决方案,请分享)。
现在我需要一个查询来获取所有不同 house_lease_id 的“有效”条款。
我不希望任何类型的自定义 MySQL 函数或存储过程来执行此操作。我不知道从哪里开始创建这个查询。我想我可以在一些子选择或连接中使用上面的查询,但我不确定我会怎么做。
任何帮助将不胜感激!
SQLFiddle 处理数据:http://sqlfiddle.com/#!9/cab159/2/0
【问题讨论】:
-
你用的是什么版本的mysql?
-
在 ORDER BY 中使用 CASE 而不是 WHERE。
-
版本:5.7.24