是的,可以返回指定的结果集。通常,返回此类结果的最有效方法是使用反连接模式。
似乎缺少的是一个谓词,该谓词标识您为其拉取新闻源的用户。
否则,任何阻止另一个用户 (B) 的用户 (A) 也将阻止所有其他用户的用户 B 的故事......没有人将能够看到来自用户 B 的故事。这似乎是一个关系表中的阻止行旨在让单个用户“阻止”另一个用户的故事。
SELECT s.id
FROM stories s
JOIN users u
ON u.id = s.posterID
LEFT
JOIN (
SELECT r.user2
FROM relationships r
WHERE r.rel = '3'
AND r.user1 = 'me'
) b
ON b.user2 = u.id
WHERE b.user2 IS NULL
AND u.schoolID='$school'
让我们分解一下,首先,消除别名为 b 的内联视图。
此查询应返回具有给定 schoolID 的所有用户发布的所有故事。
SELECT s.id
FROM stories s
JOIN users u
ON u.id = s.posterID
WHERE u.schoolID='$school'
现在,我们要“阻止”该用户(我们称他为“我”)选择阻止的任何用户的故事。
我将假设“阻塞”是如何工作的。我将假设如果user1='me'
阻止了“user2”,这意味着不应将来自“user2”的故事呈现给“我”。这将在关系表中由一行表示
(user1='me','user2',3)
如果这是正确的,那么这意味着这个查询:
SELECT r.user2
FROM relationships r
WHERE r.rel = '3'
AND r.user1 = 'me'
将返回已被用户“我”阻止的所有用户的列表。
现在的“技巧”是将此结果与第一个查询的结果进行左连接,然后丢弃我们找到匹配项的任何行。这称为“反连接”模式。请注意,IS NULL
谓词是消除匹配行的原因。
跟进:
问:如果我想避免向阻止者和被阻止者显示“故事”,我可以做一个简单的修改...
A:如果关系表中的“block”行是这样的:
(user1='me',user2,3)
我们之前认为这意味着用户“我”选择不看到来自 user2 的任何故事。
如果我们还希望将同一行解释为用户“我”也选择不允许用户 2 看到来自“我”的故事,这是我们需要做的另一项检查,但这并不难。
如果我们返回查询查找被“我”阻止的用户,(“我”不想看到来自用户 2 的故事)
SELECT r.user2
FROM relationships r
WHERE r.rel = '3'
AND r.user1 = 'me'
我们可以在该查询中交换 user1 和 user2 的位置,如下所示:
SELECT r.user1
FROM relationships r
WHERE r.rel = '3'
AND r.user2 = 'me'
这将获得选择阻止“我”的用户列表。
为了从这些用户中排除故事,我们将该查询(作为内联视图)添加到原始查询中,并执行相同的反连接模式:查找“匹配行”,然后排除任何找到匹配项的行。
在下面的查询中,新的内联视图被分配了一个别名 d(没有特别的原因,除了 'd' 看起来像 'b' 的镜像)
SELECT s.id
FROM stories s
JOIN users u
ON u.id = s.posterID
LEFT
JOIN (
SELECT r.user2
FROM relationships r
WHERE r.rel = '3'
AND r.user1 = 'me'
) b
ON b.user2 = u.id
LEFT
JOIN (
SELECT r.user1
FROM relationships r
WHERE r.rel = '3'
AND r.user2 = 'me'
) d
ON d.user1 = u.id
WHERE b.user2 IS NULL
AND d.user1 IS NULL
AND u.schoolID='$school'
注意:我还没有测试过,但如果我对要求的理解是正确的,它似乎会返回指定的结果集。
试一试,让我知道一个烟球有多大。