从多个表中选择过滤器

Posted

技术标签:

【中文标题】从多个表中选择过滤器【英文标题】:Select Filter From Multiple Tables 【发布时间】:2019-08-12 13:52:07 【问题描述】:

我有一个用户聊天系统,它有 2 个表:用户表和关注者表。我正在执行搜索,我想获得我关注的用户

users 表将此作为主键:user_idfollowers 表具有以下列following_id follower_id is_typing active

我如何加入这两个表以获得我的结果?

我一直在这样做:

function Wo_GetNearbyFriends($args = array()) 
    global $wo, $sqlConnect;
    if ($wo['loggedin'] == false || empty($args)) 
        return false;
    

    $options      = array(
        "offset" => false,
        "gender" => false,
        "name" => false,
        "distance" => false,
        "relship" => false,
        "status" => false,
        "fid_5" => false,
        "fid_6" => false,
        "fid_7" => false,
        "fid_8" => false,
        "limit" => 20
    );
    $args         = array_merge($options, $args);
    $offset       = Wo_Secure($args['offset']);
    $gender       = Wo_Secure($args['gender']);
    $name         = Wo_Secure($args['name']);
    $loc_distance = Wo_Secure($args['distance']);
    $status       = Wo_Secure($args['status']);
    $relship      = Wo_Secure($args['relship']);
    $fid_5      = Wo_Secure($args['fid_5']);
    $fid_6      = Wo_Secure($args['fid_6']);
    $fid_7      = Wo_Secure($args['fid_7']);
    $fid_8      = Wo_Secure($args['fid_8']);
    $limit        = Wo_Secure($args['limit']);
    $unit         = 6371;
    $user_lat     = $wo['user']['lat'];
    $user_lng     = $wo['user']['lng'];
    $user         = $wo['user']['id'];
    $t_users      = T_USERS;
    $t_followers  = T_FOLLOWERS;
    $distance     = 25;
    $data         = array();
    $sub_sql      = "";
    if ($loc_distance && is_numeric($loc_distance) && $loc_distance > 0) 
        $distance = $loc_distance;
    
    if ($name) 
        $name = Wo_Secure($name);
        $sub_sql .= " AND (`username` LIKE '%$name%' OR `first_name` LIKE '%$name%' OR `last_name` LIKE '%$name%') ";
    
    if (isset($status) && $status != false) 
        if ($status == 1) 
            $time = time() - 60;
            $sub_sql .= " AND `lastseen` > '$time'";
         else if ($status == 0) 
            $time = time() - 60;
            $sub_sql .= " AND `lastseen` < '$time'";
        
    
    if ($relship && in_array($relship, array_keys($wo['relationship']))) 
        $sub_sql .= " AND `relationship_id`  = '$relship' ";
    
    if ($offset && is_numeric($offset) && $offset > 0) 
        $sub_sql .= " AND `user_id` <  '$offset' AND `user_id` <> '$offset' ";
    
    if ($gender && in_array($gender, array_keys($wo['genders']))) 
        $sub_sql .= " AND `gender` = '$gender' ";
    
    if($fid_5 && is_numeric($fid_5) && $fid_5 > 0)
        $sub_sql .= " AND `fid_5` = '$fid_5' ";
    
    if($fid_6 && is_numeric($fid_6) && $fid_6 > 0)
        $sub_sql .= " AND `fid_6` = '$fid_6' ";
    
    if($fid_7 && is_numeric($fid_7) && $fid_7 > 0)
        $sub_sql .= " AND `fid_7` = '$fid_7' ";
    
    if($fid_8 && is_numeric($fid_8) && $fid_8 > 0)
        $sub_sql .= " AND `fid_8` = '$fid_8' ";
    

    $sql   = "SELECT `user_id`, ( $unit * acos(cos(radians('$user_lat')) *  cos(radians(lat)) * cos(radians(lng) - radians('$user_lng')) +  sin(radians('$user_lat')) * sin(radians(lat))) ) AS distance FROM $t_users WHERE `user_id` <> '$user' $sub_sql  AND `user_id` IN (SELECT `follower_id` FROM $t_followers WHERE `follower_id` <> $user AND `following_id` = $user AND `active` = '1') AND `user_id` IN (SELECT `following_id` FROM $t_followers WHERE `follower_id` = $user AND `following_id` <> $user AND `active` = '1') AND `lat` <> 0 AND `lng` <> 0  HAVING distance < '$distance' ORDER BY `user_id` DESC LIMIT 0, $limit ";

    $query = mysqli_query($sqlConnect, $sql);

    while ($fetched_data = mysqli_fetch_assoc($query)) 
        $fetched_data['user_data']        = Wo_UserData($fetched_data['user_id']);
        $fetched_data['user_data']['age'] = Wo_GetUserCountryName($fetched_data['user_data']);
        $fetched_data['user_geoinfo']     = $fetched_data['user_data']['lat'] . ',' . $fetched_data['user_data']['lng'];
        if ($fetched_data['user_data']['share_my_location'] == 1) 
            $data[] = $fetched_data;
        
    
    return $data;

【问题讨论】:

您能否澄清您的问题,尤其是您解释查询应该做什么的部分?另外,我是否正确假设following_idfollower_id 都包含用户ID,并引用user_id @KIKOSoftware user_id 带有用户 ID,follower_idfollowing_id 带有来自用户表的用户 ID 的引用。我试图在计算他们的距离时获得用户的关注者 @GordonLinoff 请问我如何获得问题的样本数据? 您应该在问题中解释基本内容,而不是在评论中。您仍然可以对其进行编辑。我也想知道$sub_sql 包含什么。您的查询中有很多未定义的变量。 天哪,是的,你有。但这不是应该这样做的。首先,您在外部发布代码,这并不好,其次您的问题应该是minimal and repeproducible。这两者都不是。您也没有提供示例数据或完整的表模式。如您所见,提问很困难。不过,我现在会尝试回答....让我看看....这可能需要一段时间。 【参考方案1】:

这里只是加入。拥有两个用户行后,您可以对他们的数据应用距离计算。

select *
from t_users u1
join t_users u2
  on u1.user_id < u2.user_id
  and (u1.user_id, u2.user_id) in (select follower_id, following_id from t_followers)
  and (u1.user_id, u2.user_id) in (select following_id, follower_id from t_followers);

演示:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f29e1d27055575385d4b28d777fd335c

【讨论】:

我喜欢你的方法,很酷。我浏览了演示,我看到用户 1 正在关注 2 个人,用户 2 和 3。请我需要一个 sql 代码来检索他拥有的两个关注者。 @Inspired Prynce Kaka:这与您最初提出的问题不同。如果您不希望那些既被关注又关注自己的用户(在演示中:用户 1 关注用户 2,而用户 2 自己关注用户 1,所以这是我们选择的那对),那么只需删除不想要的子句(这是其中之一我查询中的两个and ...)。

以上是关于从多个表中选择过滤器的主要内容,如果未能解决你的问题,请参考以下文章

从多个表中过滤并删除空列

使用多个相互构建的组合框过滤表单

从数据表中检索信息

高级过滤器,为1行选择了多个条件

使用 Javascript 过滤多个 HTML 表中的 JSON 数据

闪亮的动态/条件过滤选择多个输入(selectizeInput,多个= TRUE)