如何从表中的2个值中INNER JOIN正确的值,其中1个正确

时间:2019-03-03 19:46:04

标签: php mysql sql

我需要选择与当前用户相反的u1或u2并将其内部加入,以显示具有正确图片/ id的正确朋友列表

输入ID

$sess_id = $_SESSION['user']['id'];

关系表

id      u1_fk    u2_fk     u_action     status
-------------------------------------------------
 1       1        2            2          5
-------------------------------------------------
 1       3        1            3          5

详细信息:

  • Id是自动增量ID
  • u1_fk是参与(提交朋友请求)的第一个用户ID
  • u2_fk是另一个用户的ID(得到好友请求的用户)
  • u_action是最后一个执行操作的用户(例如,发送了好友请求,拒绝/接受了好友请求,阻止了其他用户,等等)

用户表

user_id    user_username          user_picture
-------------------------------------------------
 1           someusername           me.jpg       
-------------------------------------------------
 2           anotherusername      another.jpg
-------------------------------------------------
 3           thirdusername         third.jpg

SQL + PHP (在此我对user_id进行INNER JOIN u_action):

$sql = "SELECT t1.id as id, "
        . " t1.u1_fk as u1, "
        . " t1.u2_fk as u2, "
        . " t2.user_id as userid, "
        . " t2.user_username as username, "
        . " t2.user_picture as picture "
        . " FROM relationships t1 "
        . " INNER JOIN users t2 "
        . " ON t1.u_action = t2.user_id "
        . " WHERE (t1.u1_fk = :user_one "
        . " OR t1.u2_fk = :user_two) "
        . " AND t1.relationship_status = 5 ";

$stmt = $dbCon->prepare($sql);
$stmt->bindParam(":user_one", $sess_id);
$stmt->bindParam(":user_two", $sess_id);
$stmt->execute();
$count = $stmt->rowCount();
if ($count > 0) {
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

我以为我可以使用u_action,但这显然仅对其中之一有效,因为它是该字段中存储的2个用户ID之一。

所以我怎么知道每当我的查询应该内部连接u1u2时,我有点困惑,我希望有人可以帮助我,我正在考虑进行2个查询并对所有查询进行排序结果并删除用户自己的ID并在第二个查询中执行where in子句,但是我想知道是否可以仅通过1个查询来完成。

数据库的结果应该是

在这个特定示例中,从sess_id为1的数据库中得到的结果是我想要的:

id      u1_fk    u2_fk      userid     username         picture
------------------------------------------------------------------
 1       1        2            2     anotherusername   another.jpg
------------------------------------------------------------------
 1       3        1            3      thirdusername     third.jpg

在这个特定示例中,我想从数据库得到的结果是sess_id = 2

id      u1_fk    u2_fk      userid     username         picture
------------------------------------------------------------------
 1       1        2            2     someusername   me.jpg
------------------------------------------------------------------

2 个答案:

答案 0 :(得分:2)

假设关系是从U1到U2的一种方式,那么它很简单:

select u.*
from relationships r
inner join users u on r.u2_fk = u.id
where r.u1_fk = ?

我不知道行动或地位意味着什么。

如果使您的dB字段在关系表中更具描述性,则可以使事情变得更加清晰:user_id和friend_id。然后很明显,您想要将Relationship.friend_id加入到user.id中,并按Relationship.user_id

进行过滤

然后您还可以按状态等进行过滤。


由于您已经添加了所需的结果,因此我看到您希望在结果中同时包含u1_fk和u2_fk。当然可以做到这一点,但是,这使IMO更加混乱。

我建议当友谊被接受时,为新朋友创建一个新行。这样,当您要查找某个用户的所有朋友时,只需匹配u1_fk(即user_id),并且朋友将始终是u2_fk(friend_id)。

然后,每个朋友可以独立控制他们想如何联系,即,您可以阻止我,也可以我阻止您。 -我的两分钱。让您的协会做一件事情。


查看架构可能会有所帮助:

User    Relationship    User
           id
id ---->  u1_fk
          u2_fk <------- id

这很容易弄清楚。但是,您想要的更像是

User    Relationship    User
           id
 id -----> u1_fk <------ id
     \---> u2_fk <---/

因此,我首先从按关系过滤的角度来看待它,然后在匹配时添加用户信息:

select r.id, r.u1_fk, r.u2_fk, 
       coalesce(u1.user_id, u2.user_id) userid,
       coalesce(u1.username, u2.username) username,
       coalesce(u1.user_picture, u2.user_picture) picture
from relationship r
left join user u1 on r.u1_fk = u1.id
left join user u2 on r.u1_fk = u2.id
where u1_fk = ? or u2_fk = ?

但是这意味着您必须合并u1和u2中的字段。

另一种解决方案是从用户开始,加入所有可能的关系,并与不是您开始使用的用户的用户加入(GMB的优雅解决方案)

但是,如果您有以下情况会发生什么:

id    u1_fk    u2_fk
        1        2
        2        1

我认为这两种解决方案都会为您提供重复的清单。

因此,我强烈建议您(至少在您的头脑中)将u1_fku2_fk重命名为user_idfriend_id

答案 1 :(得分:2)

以下查询应该可以解决问题:

SELECT
    r.id as id,
    r.u1_fk as u1,
    r.u2_fk as u2,
    u2.user_id as userid,
    u2.user_username as username,
    u2.user_picture as picture
FROM 
    users u1
    INNER JOIN relationship r 
        ON  r.status = 5
        AND (r.u1_fk = u1.user_id OR r.u2_fk = u1.user_id)
    INNER JOIN users u2
        ON  u2.user_id <> u1.user_id
        AND (r.u1_fk = u2.user_id OR r.u2_fk = u2.user_id) 
WHERE 
    u1.user_id = :sessid

u1代表当前会话ID的users记录,u2JOIN插入为关系另一端的用户。

demo on DB Fiddle 和您的示例数据返回,会话ID为1

| id  | u1  | u2  | userid | username        | picture     |
| --- | --- | --- | ------ | --------------- | ----------- |
| 1   | 1   | 2   | 2      | anotherusername | another.jpg |
| 1   | 3   | 1   | 3      | thirdusername   | third.jpg   |