我有复杂的 SQL QUERY 我需要一些帮助来解决以下情况:
我正在寻找具有以下条件的 SQL 查询:
SELECT * FROM Table_1,Table_2 where user_id = ’16’ // 16 = ($_SESSION[ 'SESS_USER_ID' ])
我期望的结果示例如下: 我需要什么-> 我需要显示登录 'user_id' 的所有成员的结果,这些成员不在 Table_2 'friend_status' 条件 (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 查询来显示结果,显示登录 'user_id'(16) 的所有成员不在 Table_2 'friend_status' 条件 (0,1,2) 中
问题-> 我在下面得到的结果与表 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 +
+—————————+—————————————+
答案 0 :(得分:1)
首先,去掉逗号连接,用JOIN
代替;特别是 LEFT JOIN
。此外,您基本上是通过不在两个表之间的匹配列上添加 CROSS JOIN
来执行 WHERE
。我不确定这是否是您打算做的。
试试这个查询:
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 的 LEFT JOIN
列上使用了 user_id
,与 table_2 的 user_id_request
列匹配。这是因为如果我在两个表中的 user_id
之间匹配它们,table_2
将只显示 user_id=16
的位置,其余显示为 NULL
,因此您要从中过滤的数据table_2
不会出现。在查询的 SELECT ..
部分,我使用了两个操作,COALESCE
和 CASE
表达式。 CASE
表达式用于过滤掉当前的 user_id
并在它匹配条件时赋予它 0
(零) 并赋予它 1
用于其他不符合条件的数据匹配。我分配了别名 Chk
并在 HAVING
上的查询结束时使用它。对于 COALESE
部分,我首先从 user_id
返回任何 table_2
,如果 user_id
是 {{,然后从 table_1
返回 table_2
1}}。
编辑:不使用 NULL
,检查 HAVING
处的 CASE
表达式,例如:
WHERE
答案 1 :(得分:1)
看来您基本上需要从用户表到已加好友或待处理的人的左连接。您不清楚此人是否被标记为 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 注入持开放态度。
答案 2 :(得分:1)
我不确定以下哪一项对您的真实项目数据会表现得更好,因此我建议您对两者进行基准测试,看看其中一个的表现是否明显优于另一个。
代码:(Demo)
在准备好的语句中需要 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
);
左连接在准备好的语句中只需要 1 个占位符:
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 |