我有一张这样的表:
// questions_and_answers
+----+---------------+------------------------+---------+---------+
| id | subject | body | related | deleted |
+----+---------------+------------------------+---------+---------+
| 1 | subject1 | question1 | NULL | 0 |
| 2 | | answer1 | 1 | 0 |
| 3 | subject2 | question2 | NULL | 0 |
| 4 | | answer2 | 3 | 1 |
| 5 | | answer3 | 3 | 0 |
| 6 | subject3 | question3 | NULL | 1 |
| 7 | | answer4 | 6 | 0 |
+----+---------------+------------------------+---------+---------+
-- related column contains either NULL for questions or the id of its question for answers
如上表所示,answer2
和question3
都已删除。所以我想在搜索中过滤它们。关键是,我想过滤answer4
。因为它属于已删除的问题(question3
)。知道如何进行这样的过滤?
这是我当前的查询:
SELECT qa.*
FROM questions_and_answers AS qa
WHERE MATCH(subject,body) AGAINST (:entry)
AND deleted = 0
ORDER BY id DESC
LIMIT :page, 10;
如您所见,它仅过滤已删除的帖子。它并不关心过滤属于已删除问题的答案。
答案 0 :(得分:2)
如果只有一个级别的关系 - 对于 r 的任何行, r' 存在,那么 r' .related
= r .id
, r 。related IS NULL
- 您可以将问题加入到答案中并检查问题deleted
或使用NOT EXISTS
检查是否存在已删除的父记录。
LEFT JOIN
变体:
SELECT qa1.*
FROM questions_and_answers qa1
LEFT JOIN questions_and_answers qa2
ON qa2.id = qa1.related
WHERE MATCH(qa1.subject, qa1.body) AGAINST (:entry)
AND qa1.deleted = 0
AND coalesce(qa2.deleted, 0) = 0
ORDER BY qa1.id DESC
LIMIT :page, 10;
NOT EXISTS
变体:
SELECT qa1.*
FROM questions_and_answers qa1
WHERE MATCH(qa1.subject, qa1.body) AGAINST (:entry)
AND qa1.deleted = 0
AND NOT EXISTS (SELECT *
FROM questions_and_answers qa2
WHERE qa2.id = qa1.related
AND qa2.deleted = 1)
ORDER BY qa1.id DESC
LIMIT :page, 10;
答案 1 :(得分:1)
好的问题和答案可能属于单独的表格;这样你就不会有这个问题。在这种情况下,您可能会在一对多关系中使用简单连接。您可以使用CTE模仿它:
1,5,9,13
如果答案显示为自己的行,那绝对必要:
with q as (
select * from questions_and_answers
where related is null and deleted = 0
), a as (
select * from questions_and_answers
where related is not null and deleted = 0
)
select *
from q left outer join a on a.related = q.related
order by q.id, a.id;
我只是意识到你在MySQL上,所以你可能没有CTE和/或分析功能。希望这对你有用。
答案 2 :(得分:0)
您可以添加另一个AND
运算符,以使用相关子查询断言已删除父级的存在,并修改条件以使整体查询更加优化:
SELECT qa.*
FROM questions_and_answers AS qa
WHERE MATCH(subject,body) AGAINST (:entry)
AND deleted = 0
AND (qa.related IS NULL OR
NOT EXISTS (SELECT 1
FROM questions_and_answers qaa
WHERE qa.related = qaa.id AND qaa.deleted = 1)
)
ORDER BY id DESC
LIMIT :page, 10;