【问题标题】:members list SQL query whitout showing mutual friends, pending approval friends, blocked friends成员列表SQL查询不显示共同好友、待审批好友、已屏蔽好友
【发布时间】:2021-10-07 09:59:35
【问题描述】:

我有复杂的 SQL QUERY 我需要针对以下情况的一些帮助:

我正在寻找符合以下条件的 SQL 查询:

SELECT *  FROM Table_1,Table_2 where user_id = ’16’ // 16 = ($_SESSION[ 'SESS_USER_ID' ])
  • 条件 1 -> 不显示自己(当前登录用户 ID。=> 16(我是我)($_SESSION[ 'SESS_USER_ID' ]))
  • CONDITION 2 -> 不要在列表中显示 user_id 25、26、27、28,因为它们已经在 table_2 中,对于 user_id ='16' 和 CONDITION 0,1 的某些条件来自friend_status
  • 条件 3 -> 按符号更新订购

我期望的结果示例如下: 我需要什么-> 我需要显示登录 'user_id' 的所有成员的结果,这些成员不在 Table_2 'friend_status' CONDITION (0,1,2) 中

在下表结果中,您可以看到登录 'user_id'(本例中为 16)无法看到 Table_2 CONDITION (0,1,2) 中的其他 'user_id' 包括他自己作为登录 'user_id' ( 16)

//Perfect SQL results for me.
+—————————+—————————————+
+ user_id +signupdate   + 
+—————————+—————————————+
+   23    + 2020-11-30  +
+—————————+—————————————+
+   24    + 2020-11-30  +
+—————————+—————————————+
+   28    + 2020-11-30  +
+—————————+—————————————+
+   21    + 2020-11-30  +
+—————————+—————————————+

我需要什么 -> 我需要一个 SQL QUERY 来显示结果,显示登录 'user_id'(16) 不在 Table_2 'friend_status' CONDITION (0,1,2) 中的所有成员

问题-> 我在下面得到的结果与 Table_2 请求的“friend_status”条件 (0,1,2) 不匹配。

为什么?因为登录 'user_id' 不应该在完整成员页面结果中看到所有 'friend_status' CONDITION (0,1,2) 无条件 (0,1,2)

为什么?因为这些 SQl 结果 CONDITION (0,1,2) 显示在每个 CONDITION (0,1,2) 的 3 个不同结果页面的别处 -> 不是今天的主题。


//Wrong SQL results for me.
+—————————+—————————————+
+ user_id +signupdate
+—————————+—————————————+
+   16    + 2020-11-30  + <— SHOULD DO NOT SHOW, CONDITION-> ITS ME “login”  $user_id = ’16’
+—————————+—————————————+
+   23    + 2020-11-30  +
+—————————+—————————————+
+   24    + 2020-11-30  +
+—————————+—————————————+
+   25    + 2020-11-30  +<— SHOULD NOT SHOW -> TABLE_2  CONDITION user_id = ( $_SESSION[ 'SESS_USER_ID' ])=’16’ AND CONDITION2 friend_status= ‘0’(Pending approval Mutual friends)
+—————————+—————————————+
+   26    + 2020-11-30  +<— SHOULD NOT SHOW -> TABLE_2 CONDITION user_id = ( $_SESSION[ 'SESS_USER_ID' ])=’16’ AND CONDITION2 friend_status= ‘0’ (Pending approval Mutual friends)
+—————————+—————————————+
+   27    + 2020-11-30  +<— SHOULD NOT SHOW -> TABLE_2 CONDITION user_id = ( $_SESSION[ 'SESS_USER_ID' ])=’16’ AND CONDITION2 friend_status= ‘1’ (Mutual friends)
+—————————+—————————————+
+   28    + 2020-11-30  +<— SHOULD NOT SHOW -> TABLE_2 CONDITION user_id = ( $_SESSION[ 'SESS_USER_ID' ])=’16’ AND CONDITION2 friend_status= ‘2’ (Blocked)
+—————————+—————————————+
+   21    + 2020-11-30  +
+—————————+—————————————+


TABLE_2(朋友关系表) friend_status=‘0’ -> 这意味着‘user_id’等待‘user_id_resquest’接受友谊 -> 登录‘user_id’时不显示在完整成员列表中 friend_status='1' -> 这个 'user_id' 和 'user_id_resquest' 已经是共同的朋友。 -> 登录 user_id 不显示在完整成员列表中 friend_status='2' -> 这意味着 'user_id' 被 'user_id_resquest' 阻止 -> 不显示在当前登录 user_id 的成员列表中

+——————————————+—————————+——————————————+—————————————————+
+friendship_id + user_id + user_id_request + friend_status+
+——————————————+—————————+——————————————+—————————————————+
+   1          +   16    +        26    +        0        +//0->Pending
+——————————————+—————————+——————————————+—————————————————+
+   2          +   16    +        25    +        0        +//0->Pending
+——————————————+—————————+——————————————+—————————————————+
+   3          +   16    +        27    +        1        +//1->Mutual
+——————————————+—————————+——————————————+—————————————————+
+   4          +   21    +        27    +        1        +//1->Mutual
+——————————————+—————————+——————————————+—————————————————+
+   5          +   16    +        28    +        2        +//2 ->blocked
+——————————————+—————————+——————————————+—————————————————+

TABLE_1(所有用户的表)

+—————————+—————————————+
+ user_id + signupdate  +
+—————————+—————————————+
+   16    + 2020-11-30  + 
+—————————+—————————————+
+   23    + 2020-11-30  +
+—————————+—————————————+
+   24    + 2020-11-30  +
+—————————+—————————————+
+   25    + 2020-11-30  +
+—————————+—————————————+
+   26    + 2020-11-30  +
+—————————+—————————————+
+   27    + 2020-11-30  +
+—————————+—————————————+
+   28    + 2020-11-30  +
+—————————+—————————————+

【问题讨论】:

  • 我迷路了。通过显示您开始使用的数据,然后解释条件并显示您想要的结果,您的解释将真正受益。
  • 这不是一个好的问题标题。请edit更好地表达您的问题的症结。
  • 我们需要朋友状态 = 2 的样本数据才能拥有minimal reproducible example
  • 如果状态为2会怎样?你说这意味着用户被阻止但没有提到它是否应该显示在结果中。数据样本也没有任何带有status=2的单元格。
  • friend_status = '0' // 待处理,friend_status = '1' //共同好友,friend_status = '2' // 已屏蔽

标签: php mysql sql


【解决方案1】:

首先,去掉逗号连接,将其替换为JOIN;特别是LEFT JOIN。此外,您基本上是通过不在两个表之间的匹配列上添加WHERE 来执行CROSS JOIN。不过,我不确定这是否是您打算做的。

试试这个查询:

SELECT COALESCE(t2.user_id,t1.user_id) AS user_id,
      t1.signupdate,
      CASE 
           WHEN t2.user_id='16'/*($_SESSION[ 'SESS_USER_ID' ])*/ 
              AND friend_status IN (0,1) THEN 0
           WHEN t1.user_id='16'/*($_SESSION[ 'SESS_USER_ID' ])*/ THEN 0
           ELSE 1 END AS Chk
FROM Table_1 AS t1 LEFT JOIN Table_2 AS t2 
ON t1.user_id = t2.user_id_request 
HAVING Chk=1;

在查询中,我在 table_1 的 user_id 列上使用了 LEFT JOIN,与 table_2 的 user_id_request 列匹配。这是因为如果我在两个表中的user_id 之间匹配它们,table_2 只会显示user_id=16 的位置,其余的显示为NULL,因此您要从table_2 过滤的那些数据将不会出现。在查询的SELECT .. 部分,我使用了两个操作,COALESCECASE 表达式。 CASE 表达式用于过滤掉当前的user_id,如果它匹配条件则给它0(零),对于不匹配的其他数据给它1。我为此分配了别名Chk,并在HAVING 的查询末尾使用它。对于COALESE 部分,我首先从table_2 返回任何user_id,然后如果table_2NULL,则从table_1 返回user_id

Demo fiddle

编辑:不使用HAVING,检查CASEWHERE处的表达式,如:

SELECT COALESCE(t2.user_id,t1.user_id) AS user_id,
      t1.signupdate
FROM Table_1 AS t1 LEFT JOIN Table_2 AS t2 
ON t1.user_id = t2.user_id_request
WHERE CASE 
           WHEN t2.user_id='16'/*($_SESSION[ 'SESS_USER_ID' ])*/ 
                   AND friend_status IN (0,1) THEN 0
           WHEN t1.user_id='16'/*($_SESSION[ 'SESS_USER_ID' ])*/ THEN 0
           ELSE 1 END=1;

【讨论】:

  • 我不确定我是否支持使用 HAVING。这不能用 ON 和 WHERE 逻辑来完成吗?
  • 是的,它可以@mickmackusa。只需将CASE 表达式转换为WHERE。请检查我的编辑。
  • 那么你是说如果你只使用WHERE 16 NOT IN (t1.user_id, t2.user_id),逻辑就成立了吗? (因为上班没测试)这样$_SESSION[ 'SESS_USER_ID' ]就可以绑定一次prepared statement了。
  • ...我不知道,我没有时间研究这个。我只是觉得这些sql查询没有想象中那么优雅。
  • 哦,是的,我忘记了。虽然我很好奇如果状态是2会发生什么?
【解决方案2】:

看来您基本上需要从用户表到已加好友或待处理的人的左连接。您不清楚此人是否被标记为 ID = 2。如果他们被标记为被阻止,您是否不希望他们的名字显示为可能的朋友/朋友请求?所以简而言之,您想要任何不是您(当前登录用户)并且尚未被请求为朋友 = 0,确认为朋友 = 1,或已经请求但被阻止的用户 = 2 的人。为什么要显示您想要的某人的名字被屏蔽了。

select
      T1.*
   from
      Table1 T1
   where
          NOT T1.User_ID = ($_SESSION[ 'SESS_USER_ID' ])
      AND T1.User_ID NOT IN ( select T2.user_id_request
                                 from Table2 T2
                                 where T2.User_ID = ($_SESSION[ 'SESS_USER_ID' ])) 
   order by 
      T1.SignupDate

 

只需确保正确参数化查询,而不是使用直接变量来构建查询字符串。您将对 sql-injection 敞开心扉。

【讨论】:

  • 条件 2:user_id =’16’ and CONDITION 0,1 from friend_status -- 我认为我们需要一个更好的 minimal reproducible example。为什么不使用T1.User_ID != ($_SESSION[ 'SESS_USER_ID' ]) 而不是WHERE NOTNOT EXISTS()呢?
  • @mickmackusa,where NOT user = 16 (via session) 与 user_id != 16 相同。至于朋友条件,人们放了他们可能不需要的东西。您是否阅读了我的答案的主要上下文/解释?我们正在努力获得他们需要的东西,而不仅仅是描述的东西。在可能的期望想要的行之间阅读。
【解决方案3】:

我不确定以下哪一项会在您的实际项目数据中表现更好,因此我建议您对两者进行基准测试,看看其中一个的表现是否明显优于另一个。

代码:(Demo)

  1. 在准备好的语句中需要 2 个占位符的 Table_1 每一行的子查询(可能表现不佳)

    SELECT user_id, signupdate
    FROM Table_1 AS t1
    WHERE user_id != 16
      AND NOT EXISTS(
                SELECT 1
                FROM Table_2
                WHERE user_id_request = t1.user_id
                  AND user_id = 16
              );
    
  2. 在准备好的语句中只需要一个占位符的左连接:

    SELECT t1.user_id, t1.signupdate
    FROM Table_1 AS t1
    LEFT JOIN Table_2 AS t2 ON t1.user_id = t2.user_id_request
    WHERE 16 NOT IN (t1.user_id, COALESCE(t2.user_id,0))
      AND t2.friendship_id IS NULL;
    

两个输出:

| user_id | signupdate |
| ------- | ---------- |
| 23      | 2020-11-30 |
| 24      | 2020-11-30 |
| 21      | 2020-11-30 |

【讨论】:

  • @Gordon 你有时间看看我的建议吗?我想知道我没有给出任何不好的建议。如果这些技术有什么愚蠢/不好的地方,请纠正我。例如,我是否应该使用IN 来缩短语法,因为它会产生不必要的性能成本?
  • 您对 N°2 答案的方法非常好,因为据我了解 => 只要我的 user_id ='16' 存在于 table_2 中的任何 'friendstatus' (0,1,2) table_2,QUERY 正在按我的意愿工作。我在成员列表 (user_id ='16' )(工作条件)中没有看到自己,并且在成员列表查询中没有看到与我的 user_id ='16' 关联的任何 'user_id_request'。这非常有效,成员列表仅显示我在 table_2 中没有关系的成员。感谢您的帮助!
猜你喜欢
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多