表:
预订:id,user_id,object_id,date1,...
booking_status :id,book_id,status
状态为int,范围从1到9(请求,确认,付费,由用户取消和那种东西),所以我需要所有预订,其中状态至少为4(这意味着付费)但没有更大的值比4(这意味着取消等)。
直到SELECT现在看起来像这样(我遗漏了一些字段(...)来缩短它):
SELECT b.date1, ..., u.name FROM bookings b
LEFT JOIN user u ON (b.user_id = u.id)
LEFT JOIN booking_status bs ON (b.id=bs.book_id)
WHERE ((b.object_id=$object_id) AND (bs.status NOT IN (5,6,7,8,9)));"
...但它仍然会选择预订状态大于4的预订。任何想法我需要如何更改查询??
非常感谢你!
更新:再次感谢大家,我很惊讶你提出了多少好主意!有很多方法可以做到,我从你身上学到了很多,所以再次感谢你!我将尝试你的所有建议,看看性能,现在我把你的解决方案混合到这个查询,现在有效,但我需要进一步测试:
SELECT b.date, ..., u.name FROM bookings b
LEFT JOIN user u ON (b.user_id = u.id)
LEFT JOIN booking_status bs ON (b.id=bs.book_id AND bs.status<=4)
WHERE (b.object_id=$object_id) HAVING MAX(bs.status)=4
它不会返回多行,但会返回4行,排除超过4的行并且没有子查询......
编辑2:我再次编辑了查询... HAVING MAX(bs.status)= 4然后工作......
编辑3:对不起,在测试了不同的案例之后,我不得不承认我的说法太快了,说它有效......
答案 0 :(得分:3)
如果我理解正确,你需要的是:
SELECT b.date1, ..., u.name
FROM bookings b
LEFT JOIN user u ON b.user_id = u.id
WHERE b.object_id = ...
AND EXISTS
( SELECT 1
FROM booking_status bs
WHERE bs.book_id = b.id
AND bs.status = 4
)
AND NOT EXISTS
( SELECT 1
FROM booking_status bs
WHERE bs.book_id = b.id
AND bs.status > 4
)
;
您当前查询的问题在于它会过滤掉bs.status > 4
所有已加入的行,但它不会过滤掉与{{1}的联接行具有相同bookings.id
的联接行}}
答案 1 :(得分:1)
受到Ruakh解决方案的启发而没有相关的子查询:
select ...
from bookings b
join (select book_id from booking_status group by book_id having max(status) = 4
) bs on b.id = bs.book_id
left join user u on b.user_id = u.id
答案 2 :(得分:1)
这是一个没有子查询的方法:
SELECT b.date1, ..., u.name
FROM bookings b
LEFT JOIN user u ON u.id = b.user_id
JOIN booking_status bs1
ON bs1.book_id = b.id AND bs1.status = 4
LEFT JOIN booking_status bs2
ON bs2.book_id = b.id AND bs2.status > 4
WHERE b.object_id = $object_id
AND b2.book_id IS NULL
此查询将删除任何存在同一ID大于4的状态的行。
答案 3 :(得分:1)
另一种方式
SELECT id,
user_id,
object_id,
date1
FROM bookings b
INNER JOIN (SELECT book_id
FROM booking_status
GROUP BY book_id
HAVING MAX(CASE
WHEN status >= 4 THEN status
END) = 4) bs
ON bs.book_id = b.id
(或响应评论时没有subselect的版本)
SELECT b.id,
b.user_id,
b.object_id,
b.date1
FROM bookings b
INNER JOIN booking_status bs
ON bs.book_id = b.id
GROUP BY b.id /* Other RDBMSs would require all columns listed*/
HAVING MAX(CASE
WHEN bs.status >= 4 THEN bs.status
END) = 4