在mysql数据库中正确连接1:n:1:1关系
我现在正在开发一个管理租赁流程的系统,我想知道如何有效地查询所有可租赁的对象,如果该对象是目前租赁的,那么使用当前租赁对象的人名。否则,该列中应该有NULL 我的桌子看起来像: 反对 人 出租 租赁对象 我想要的结果应该如下所示:在mysql数据库中正确连接1:n:1:1关系,mysql,sql,database-design,Mysql,Sql,Database Design,我现在正在开发一个管理租赁流程的系统,我想知道如何有效地查询所有可租赁的对象,如果该对象是目前租赁的,那么使用当前租赁对象的人名。否则,该列中应该有NULL 我的桌子看起来像: 反对 人 出租 租赁对象 我想要的结果应该如下所示: | object_id | object_name | rented_to | ------------------------------------------- | 1 | Object A | John Doe |
| object_id | object_name | rented_to |
-------------------------------------------
| 1 | Object A | John Doe |
| 2 | Object B | Max Muster |
| 3 | Object C | NULL |
| 4 | Object D | NULL |
| 5 | Object E | Max Muster |
-------------------------------------------
到目前为止,我得到的是:
SELECT `object_id`, `object_name`, `person_name` FROM `object`
LEFT JOIN `rental2object` ON `object_id` = `object_object_id`
LEFT JOIN `rental` ON `rental_id` = `rental_rental_id` AND `rental_state` = 'open'
LEFT JOIN `person` ON `person_id` = `person_person_id`
GROUP BY `object_id`
明显的问题是,我不知道如何在分组时以正确的方式进行聚合
实现我的目标最有效的方法是什么?谢谢你的帮助
编辑
更正了预期结果,因此对象B也租给了Max Muster。关于您的问题
对象2和5都在租赁4中。但是,根据您的预期结果,您正在以不同的方式处理这两个问题。对象E和对象B应具有相同的行为,因为它们处于相同的租赁期。如果没有,你应该解释witch是判断产品是否有相关人员的标准
分组
要符合SQL92,您应该在select子句中包含所有未聚合的列:
SELECT `object_id`, `object_name`, `person_name` as rented_to
FROM `object`
...
GROUP BY `object_id`, `object_name`, `person_name`
要符合SQL99,您应该在select子句中包含所有非聚合列,这些列不依赖于函数,在您的情况下,它们是对象id和对象名称之间的依赖项:对象id->对象名称字段RETATE将依赖函数分解为person,然后您可以编写:
SELECT `object_id`, `object_name`, `person_name` as rented_to
FROM `object`
...
GROUP BY `object_id`, `person_name`
MySQL 5.7.5及更高版本实现了函数依赖性检测,那么最后一个选择是有效的,但我建议您,为了可读性,使用第一个选择
请阅读以了解更多信息,仅按参数详细信息查看完整组
表演
确保您有以下各项的索引:
object:object_id是主键,那么索引是隐式的
rental2object:object\u object\u id可能是与其他字段的复合索引,但请确保object\u object\u id是索引上的第一个字段
租金:租金id和租金状态包含两个字段的复合索引
person:person\u id是主键,那么索引是隐式的
试试这个
SELECT
o.object_id,
o.object_name,
p.person_name AS rent_to
FROM
rental2object ro
RIGHT JOIN object o ON ro.object_object_id = o.object_id
LEFT JOIN rental r ON ro.rental_rental_id = r.rental_id AND r.rental_status = 'open'
JOIN person p ON r.person_person_id = p.person_id
“再次查看”查询与所需输出不匹配。我根据返回对象b的最后一个状态的预期结果进行思考,但OPs解决方案认为该状态已打开并出租给Max Muster。查询可能需要where in max测试来查找对象的最后状态,并且不应测试open in on子句。感谢您通过处理使我了解该组。在阅读了相关文章后,我想这可能就是我想要的:选择object_id,object_name,MAXperson\u name as rented\u to FROM object LEFT JOIN rental2object ON object\u object\u id LEFT JOIN rent ON rent\u id=rent\u rent\u id AND rent\u state='open'LEFT JOIN person ON person\u id=person\u person\u id GROUP BY object\u idb是否适用于这种情况?仅当一个对象在同一时间处于多个打开的租金中时才有意义时间不幸的是,mysql没有排名函数来获取分区上的最后一个用户。我想您可能会对这样的功能感兴趣,但此功能仅在SQL Server、Oracle和PostgreSQL上可用。不在MySQL中您的SELECT语句中有列在GROUP BY中不存在。对象2和5都在4中。但你在处理这两个问题时,会根据你的预期结果采取不同的方式。对象E和对象B都应该是相同的行为,都与最大集合有关,不是吗?为什么对象B有一个与person相关的空值?好的,我看到你的编辑,然后检查我的答案,被某个麻瓜投票否决了,我不知道为什么。顺便说一句,谢谢这个详细的问题,我根据它写了一个。我的学生会恨你的。。。或欣赏;谢谢你的欣赏。这不对,连接到对象应该是一个正确的外部连接来选择所有对象。我投了反对票,因为问题不在from子句上,而且你的方法是错误的。我取消了投票,但考虑一下。
SELECT `object_id`, `object_name`, `person_name` FROM `object`
LEFT JOIN `rental2object` ON `object_id` = `object_object_id`
LEFT JOIN `rental` ON `rental_id` = `rental_rental_id` AND `rental_state` = 'open'
LEFT JOIN `person` ON `person_id` = `person_person_id`
GROUP BY `object_id`
SELECT `object_id`, `object_name`, `person_name` as rented_to
FROM `object`
...
GROUP BY `object_id`, `object_name`, `person_name`
SELECT `object_id`, `object_name`, `person_name` as rented_to
FROM `object`
...
GROUP BY `object_id`, `person_name`
SELECT
o.object_id,
o.object_name,
p.person_name AS rent_to
FROM
rental2object ro
RIGHT JOIN object o ON ro.object_object_id = o.object_id
LEFT JOIN rental r ON ro.rental_rental_id = r.rental_id AND r.rental_status = 'open'
JOIN person p ON r.person_person_id = p.person_id
SELECT `object_id`, `object_name`,
case
when rental_state = 'Open' then `person_name`
when r1.rental_rental_id is null then null
else `rental_state`
end as RentedTo
FROM `object`
LEFT JOIN `rental2object` r1 ON `object_id` = r1.`object_object_id`
LEFT JOIN `rental` ON `rental_id` = r1.`rental_rental_id`
LEFT JOIN `person` ON `person_id` = `person_person_id`
where r1.rental_rental_id =
(select max(r2.`rental_rental_id`)
from `rental2object` r2
where r2.`object_object_id` = r1.`object_object_id`
group by r2.`object_object_id`)
or r1.rental_rental_id is null
GROUP BY `object_id`;