我正在尝试做一些MySQL魔术,而且我遇到了一堵墙。
基本上,这将是将相关帖子拉入用户主要“新闻源”页面的代码。但是,它不是从朋友那里拉扯帖子的;它正在从系统中同一组内的任何人那里提取帖子,但它(显然)不应该显示阻止他们的人的帖子。我理解JOIN过程,但是我无法找到后一部分的正确语法。
这是当前的查询:
SELECT stories.id
FROM stories
JOIN users ON stories.posterID=users.id
JOIN relationships ON relationships.user1=stories.posterID
WHERE users.schoolID='$school'
AND (relationships.rel <> '3' WHERE relationships.user2=stories.posterID)
“rel”字段只是用户与用户“关系”的标志;在这种情况下,3表示它们已被阻止,但由于显而易见的原因,这些用户之间可能根本没有关系输入。有没有办法去做呢?
答案 0 :(得分:1)
我想我可以看到你想要做什么,试一试:
SELECT
stories.id
FROM
stories
INNER JOIN
users ON users.id = stories.posterID
INNER JOIN
relationships ON relationships.user1 = users.id
WHERE
users.schoolID = '$school'
AND
NOT EXISTS (
SELECT
1
FROM
relationships AS r
WHERE
r.user1 = users.id
AND
r.user2 = stories.posterID
AND
r.rel = 3
)
答案 1 :(得分:0)
是的,可以返回指定的结果集。通常,返回此类结果的最有效方法是使用反连接模式。
似乎缺少的是一个谓词,用于标识您正在提取新闻源的用户。
如果没有这个,那么阻止另一个用户(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
谓词是消除匹配行的原因。
问:如果我想避免向拦截器和被阻止的人显示“故事”,我可以进行简单的修改......
答:如果关系表中的“阻止”行如下所示:
(user1='me',user2,3)
我们之前认为用户'我'选择不看用户2的任何故事。
如果我们也希望将同一行解释为意味着用户'我'也选择不允许用户2看到'我'的故事,这是我们需要做的另一项检查,但这并不困难。
如果我们回到查询中查找被“我”阻止的用户,(其中“我”不希望看到来自user2的故事)
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'
注意:我没有测试过,但是如果我对需求的理解是合理的话,似乎会返回指定的结果集。
给它一个旋转,让我知道有多大的烟球。