我需要从具有“早晨”事件的聊天(“普通”和“服务”类型)中选择user.id = 1的所有消息(传入和传出)
显示它们(附加图像上的选择1)
SELECT *
FROM `message`
JOIN chat
ON message.chat_id = chat.id
JOIN event
ON chat.event_id = event.id
JOIN chat_type
ON chat.chat_type_id = chat_type.id
WHERE (sender = 1 or recipient = 1)
AND event.name = 'morning'
但我必须排除“服务”消息,我是发件人。 这很好,但我不喜欢它(在图像上选择2)
SELECT *
FROM `message`
JOIN chat
ON message.chat_id = chat.id
JOIN event
ON chat.event_id = event.id
JOIN chat_type
ON chat.chat_type_id = chat_type.id
WHERE (sender = 1 or recipient = 1)
AND event.name = 'morning'
AND message.id NOT IN (
SELECT message.id
FROM `message`
JOIN chat
ON message.chat_id = chat.id
JOIN event
ON chat.event_id = event.id
JOIN chat_type
ON chat.chat_type_id = chat_type.id
WHERE (sender = 1 or recipient = 1)
AND sender = 1
AND chat_type.name = 'service'
)
架构并选择结果:
答案 0 :(得分:0)
我会在union
条件中使用or
而不是where
条件,然后您可以在没有子查询的情况下进行过滤:
(
SELECT *
FROM `message`
JOIN chat ON message.chat_id = chat.id
JOIN event ON chat.event_id = event.id
JOIN chat_type ON chat.chat_type_id = chat_type.id
WHERE sender = 1
AND event.name = 'morning'
AND chat_type.name <> 'service'
)
UNION
(
SELECT *
FROM `message`
JOIN chat ON message.chat_id = chat.id
JOIN event ON chat.event_id = event.id
JOIN chat_type ON chat.chat_type_id = chat_type.id
WHERE recipient = 1
AND event.name = 'morning'
)
MySQL目前无法使用索引来满足or
操作,因此使用union
是一种常见的优化技术。我还会考虑从查询中排除chat_type
表,并在chat_type_id<>2
上过滤。沿着同样的路线,您也可以摆脱event
表。即使您决定保留此表,也应该对数字ID字段进行过滤,而不是对文本值进行过滤。
或者,您可以调整or
条件以在没有子查询的情况下进行过滤:
SELECT *
FROM `message`
JOIN chat ON message.chat_id = chat.id
JOIN event ON chat.event_id = event.id
JOIN chat_type ON chat.chat_type_id = chat_type.id
WHERE ((sender = 1
AND chat_type.name <> 'service')
or recipient = 1
)
AND event.name = 'morning'
答案 1 :(得分:0)
你应该解释为什么你不喜欢你的解决方案。
根据您的描述和示例,子选择是多余的且无效的:
SELECT *
FROM `message`
JOIN chat
ON message.chat_id = chat.id
JOIN event
ON chat.event_id = event.id
JOIN chat_type
ON chat.chat_type_id = chat_type.id
WHERE (message.sender = 1 or message.recipient = 1)
AND event.name = 'morning'
AND NOT (
message.sender = 1 /* or whatever your id is */
AND chat_type.name = 'service'
);
(你还应该明确地调出你选择的属性)