Php 仅显示与条件匹配的结果

Php 仅显示与条件匹配的结果,php,mysql,Php,Mysql,我正试图做一点MySQL魔术,但我遇到了一堵墙 本质上,这就是将相关帖子拉入用户主“新闻提要”页面的代码。然而,它并不是从朋友那里获取帖子;它是从系统中同一组中的任何人那里获取帖子,但是(显然)它不应该显示那些阻止它们的人的帖子。我理解连接过程,但我很难为后面的部分找到正确的语法 这是当前查询: SELECT stories.id FROM stories JOIN users ON stories.posterID=users.id JOIN relationships ON relation

我正试图做一点MySQL魔术,但我遇到了一堵墙

本质上,这就是将相关帖子拉入用户主“新闻提要”页面的代码。然而,它并不是从朋友那里获取帖子;它是从系统中同一组中的任何人那里获取帖子,但是(显然)它不应该显示那些阻止它们的人的帖子。我理解连接过程,但我很难为后面的部分找到正确的语法

这是当前查询:

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)
SELECT stories.id
来自故事
加入故事中的用户。posterID=users.id
在relationships.user1=stories.posterID上连接关系
其中users.schoolID=“$school”
和(relations.rel“3”,其中relations.user2=stories.posterID)

“rel”字段只是用户对用户“关系”的标志;在本例中,3表示它们已被阻止,尽管出于明显的原因,这些用户之间可能根本不存在关系条目。有什么方法可以做到这一点吗?

我想我可以看到您正在尝试做什么,请尝试一下:

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 
  )

是的,可以返回指定的结果集。通常,返回此类结果的最有效方法是使用反连接模式

似乎缺少的是一个谓词,它标识您为其提取新闻提要的用户

如果没有这一点,那么阻止另一个用户(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'中的任何故事都不应该呈现给'me'。这将在关系表中用一行

(user1='me','user2',3)
如果是这样,那么这意味着此查询:

SELECT r.user2
  FROM relationships r
 WHERE r.rel = '3'
   AND r.user1 = 'me'
将返回已被用户“我”阻止的所有用户的列表

现在的“技巧”是将这个结果与第一个查询的结果进行左连接,然后丢弃找到匹配的任何行。这称为“反连接”模式。请注意,
IS NULL
谓词消除了匹配行


后续行动: Q:如果我不想同时向阻止者和被阻止者显示“故事”,我可以做一个简单的修改

A:如果关系表中的“块”行如下所示:

(user1='me',user2,3)
我们之前认为这意味着用户“我”选择不看来自user2的任何故事

如果我们还希望将同一行解释为用户“我”也选择不允许用户2查看“我”的故事,这是我们需要做的另一项检查,但这并不困难

如果我们返回查询,查找被“我”阻止的用户,(其中“我”不希望看到来自user2的故事)

我们可以在该查询中交换user1和user2的位置,如下所示:

SELECT r.user1
  FROM relationships r
 WHERE r.rel = '3'
  AND r.user2 = 'me'
这将得到一个选择阻止“我”的用户列表

为了从这些用户中排除故事,我们将该查询(作为内联视图)添加到原始查询中,并执行相同的反连接模式:查找“匹配行”,然后排除找到匹配的任何行

在下面的查询中,新的内联视图被分配了一个别名d(没有特殊原因,除了“d”看起来像“b”的镜像之外)

注意:我还没有测试它,但是如果我对需求的理解是正确的,那么它似乎会返回指定的结果集


试一试,让我知道一个烟球有多大。

你需要给我们一张表。没有模式的回答几乎是猜测。请提供架构的相关信息,我可能可以帮助您。反连接模式通常比使用不存在(相关子查询)的等效查询执行得更好。此答案中的查询似乎排除了关系表中没有至少一个对应“user1”值的用户的所有故事(由于内部联接操作)。此查询似乎还阻止了任何用户阻止的任何用户的所有故事。如果用户A阻止用户B,那么用户C和D也不会看到用户B的任何故事。如果这是一个符合您问题的答案,我对@AlexP印象深刻。因为不知道模式就很难理解查询的预期结果。“太好了!”肖恩:我补充了我的回答。我解释了我对新需求的理解,并解释了如何制定一个获取指定结果集的查询。(这是一个简单的修改,不是对整个结构的改变。)
SELECT r.user1
  FROM relationships r
 WHERE r.rel = '3'
  AND r.user2 = 'me'
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'