今天在一个业务处理流程中,需要对三张表的进行关联查询。之前碰到最多也就是两张表的联合查询,昨天和同学交流的时候,他说在写SQL时,关联查询最好少用等值连接。而现在我也想突破下常规,换中写法试试。在读大学的时候,记得学过数据库这么课,但是当时对编程几乎没有什么理解,那些知识现在也很模糊了,基本上都还给老师了。公司办公环境又不允许接入互联网,只能硬着头皮慢慢回想了。由于本项目使用了Hibernate处理数据的持久化,还要尽量接近面向对象查询这种思路。
先简单抽象下业务情景:
Device(设备) Listconferences;Conference(会议) Device device; List users; Status status; //会议的一个状态值(进行、结束)User(用户) List conferens;//映射关系A和B是多对一的双向关联, B维护关联关系B和C是多对多的双向关联,通过一张中间表,使用双方主键建立关联关系//目的假如User现在有4个用户:u1 u2 u3 u4Device有一台:d1Device下举办过3场会议: c1[u1, u2, u3] 已结束 c2[u2, u3] 进行中 c3[u2, u4] 进行中现在要查的就是Device为d1的设备下,所有没有正在参加会议的用户其实就是所有的users与 d1设备下正在参加会议的用户的差集在上情形就是:[u1, u2, u3, u4] 差 ([u2, u3] 并 [u2, u4]) = u1
最后转换成HQL语句就是
SELECT u from User u where u not in ( select User tu from tu left join tu.conferences c where c.status=? and c.device.deviceId=?)
虽然可以查出结果,但是效率到底怎么样,心里还是没底。下面在复习下那几种关联查询。
1. inner join:在表中存在至少一个匹配时,INNER JOIN 关键字返回行
Device表
device_id | device_name |
1 | 设备1 |
2 | 设备2 |
Conference表
conference_id | conference_name | device_id |
1 | 会议1 | 1 |
2 | 会议2 | 4 |
3 | 会议3 | 1 |
4 | 会议4 | 3 |
SQL:
SELECT d.device_name, c.conference_name from device d inner join conference c on d.device_id=c.device_id;
结果集:
设备1 | 会议1 |
设备1 | 会议3 |
INNER JOIN 关键字在表中存在至少一个匹配时返回行。如果 "Device" 中的行在 "Conference" 中没有匹配,就不会列出这些行。
2. left join:会从左表 (Device) 那里返回所有的行,即使在右表 (Conference) 中没有匹配的行
SELECT d.device_name, c.conference_name from device d left join conference c on d.device_id=c.device_id;
结果集:
设备1 | 会议1 |
设备1 | 会议3 |
设备2 |
3. right join: 会从右表 (Device) 那里返回所有的行,即使在左表 (Conference) 中没有匹配的行
SELECT d.device_name, c.conference_name from device d right join conference c on d.device_id=c.device_id;
结果集:
设备1 | 会议1 |
会议2 | |
设备1 | 会议3 |
会议4 |
4. full join:全连接,这个对比上面的就很好理解了。