好的,我试图通过抽象出细节来简化我的问题,但恐怕我不清楚并且不符合主持人的要求。因此,我将更详细地发布包含我的问题的完整查询以及我正在努力解决的实际查询。如果问题仍然不充分,请您就不清楚的地方发表评论,我会尽力澄清。
首先,这是返回每张床的所有分配行的当前查询:
SELECT
beds.bed_id,
beds.bedstatus,
beds.position as bed_position,
rooms.room_id,
rooms.room,
wings.wing_id,
wings.name as wing_name,
buildings.building_id,
buildings.name as building_name,
assignments.assignment_id,
assignments.student_id,
assignments.assign_dt,
assignments.assigned_by,
assignments.assignment_status,
assignments.expected_arrival_dt as arrival_dt,
assignments.room_charge_type,
students.first_name,
students.last_name,
meal_plans.name as meal_plan_name,
room_rates.rate_name
FROM
beds
LEFT JOIN
rooms ON (beds.room_id = rooms.room_id)
LEFT JOIN
wings ON (rooms.wing_id = wings.wing_id)
LEFT JOIN
buildings ON (wings.building_id = buildings.buildings_id)
LEFT JOIN assignments ON
((beds.bed_id=assignments.bed_id) AND (term_id = @term_id))
LEFT JOIN
students ON (assignments.student_id = students.student_id)
LEFT JOIN
meal_plans ON (assignments.meal_plan_id = meal_plans.meal_plan_id)
LEFT JOIN
room_rates ON (room_rate_id = room_rates.room_rate_id)
WHERE
(
(rooms.room IS NOT NULL) AND
(rooms.assignable = 1) AND
(buildings.active = 1) AND
(buildings.building_id = @building_id)
)
ORDER BY BY rooms.room;
问题是每个房间的“分配”表中可能有多行,由“assignment_status”字段区分,我希望每个分配都有一行。我想根据 assignment_status 中的值确定要选择哪个分配行。也就是说,如果分配状态为“活动”,我想要那一行,否则,如果有一行状态为“等待批准”,那么我想要那一行,等等......
Barmar 的建议如下:
LEFT JOIN (SELECT *
FROM OtherTable
WHERE <criteria>
ORDER BY CASE status
WHEN 'Active' THEN 1
WHEN 'Waiting Approval' THEN 2
WHEN 'Canceled' THEN 3
...
END
LIMIT 1) other
这非常有帮助,我尝试了这种方法:
SELECT
beds.bed_id,
beds.bedstatus,
beds.position as bed_position,
rooms.room_id,
rooms.room,
wings.wing_id,
wings.name as wing_name,
buildings.building_id,
buildings.name as building_name,
assign.assignment_id,
assign.student_id,
assign.assign_dt,
assign.assigned_by,
assign.assignment_status,
assign.expected_arrival_dt as arrival_dt,
assign.room_charge_type,
students.first_name,
students.last_name,
meal_plans.name as meal_plan_name,
room_rates.rate_name
FROM
beds
LEFT JOIN
rooms ON (beds.room_id = rooms.room_id)
LEFT JOIN
wings ON (rooms.wing_id = wings.wing_id)
LEFT JOIN
buildings ON (wings.building_id = buildings.buildings_id)
LEFT JOIN (SELECT *
FROM assignments
WHERE ((assignments.bed_id==beds.bed_id) AND (term_id = @term_id))
ORDER BY CASE assignment_status
WHEN 'Active' THEN 1
WHEN 'Waiting Approval' THEN 2
WHEN 'Canceled' THEN 3
END
LIMIT 1) assign
LEFT JOIN
students ON (assign.student_id = students.student_id)
LEFT JOIN
meal_plans ON (assign.meal_plan_id = meal_plans.meal_plan_id)
LEFT JOIN
room_rates ON (room_rate_id = room_rates.room_rate_id)
WHERE
(
(rooms.room IS NOT NULL) AND
(rooms.assignable = 1) AND
(buildings.active = 1) AND
(buildings.building_id = @building_id)
)
ORDER BY rooms.room;
但我意识到,这里的问题是 OtherTable (assignments) 基于 FK 加入到父查询中:
((beds.bed_id=assignments.bed_id) AND (term_id = @term_id))
所以我不能做子选择,因为beds.bed_id 不在子选择的范围内。因此,Barmar 的评论表明连接条件需要在子选择之外——但我无法弄清楚如何将结果限制为每个房间的一行并将连接移到子选择之外。我想知道 travelboy 使用 GROUP BY 的建议是否更有成效,但无法确定应该如何进行分组。
让我知道我是否可以提供额外的说明。
原始问题:
我需要从表 A 对另一个表中的单行进行 LEFT JOIN,表 B 满足某些条件(表 B 中可能有多个或没有满足条件的行)。如果有多行,我想根据表 B 中字段的值来选择 B 中的哪一行要加入。例如,如果 B 中有一行 status column='Active',我想要该行,如果不,如果有一行 status='Waiting Approval',我想要那一行,如果有一行 status='Canceled',我想要那一行,等等...我可以在没有子选择的情况下执行此操作吗?有一个子选择?