Group values by a common value: userid and ipaddress

前端 未结 3 2022
说谎
说谎 2021-01-27 16:06

I\'m working on a problem in my database. I\'m trying to find the users who are using multiple accounts. I have a list of user IDs and used IP addresses, like this:

Us

相关标签:
3条回答
  • 2021-01-27 16:18

    Here is my solution. Actually, I think I've created a code monster. So if anyone could find a nicer solution I would really appropriate it.

    First of all, ill need this function to check if an value is in an multidimensional array:

     function in_array_r($needle, $haystack, $strict = false) {
        foreach ($haystack as $key => $item) {
            if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
               return $key;
            }
         }
         return false;
      }    
    

    Following Array contains IP Addresses and Userids:

    $userids_using_same_ip[$ipadresss] = array("$userid1,$userid2 ....); 
    

    I will group the Persons who are posting with different accounts or Ipaddresses later in an array called: $sameuserandidcloud

    Here is my Code, first off all i will read the $userids_using_same_ip Array:

    $cloundnr=0;
    $sameuserandidcloud = array();
    foreach($userids_using_same_ip as $ip => $userids) {
        foreach($userids_using_same_ip[$ip] as $userid) {
           // In this loop i have the $ip and the $userid and im going to store them in the $sameuserandidcloud array
    
           $checkip = in_array_r($ip, $sameuserandidcloud);
           $checkuserid = in_array_r($userid, $sameuserandidcloud);
           if($checkip==false && $checkuserid==false) {
                //Create new Cloud
                $cloundnr++;
               if(!is_array($sameuserandidcloud[$cloundnr])) $sameuserandidcloud[$cloundnr] = array();
                   array_push($sameuserandidcloud[$cloundnr],$ip,$userid);        
               }
               else {
                  if($checkip != false) array_push($sameuserandidcloud[$checkip],$ip,$userid);
                  elseif($checkuserid != false) array_push($sameuserandidcloud[$checkuserid],$ip,$userid);
               }
        }
    }
    

    Now I have an Array which contains $ip and $userids which belong together. BUT its not done yet. Because I created this array in a loop there might be ips and ids that have been stored into a Cloud before other, possible matching values where added. So i need to loop the entire array again.

        while($loop!=1) {
            $break=0;
            $loop=1;
            foreach($sameuserandidcloud as $cloudid => $idanduseridarray) {
                $break=0;
                foreach($sameuserandidcloud[$cloudid] as $ipOrUserid) {
                    $check = in_array_r($ipOrUserid, $sameuserandidcloud);
                    if($check != false && $check != $cloudid) {
                        array_push($sameuserandidcloud[$check],$sameuserandidcloud[$cloudid][0]);
                        unset($sameuserandidcloud[$cloudid]);
                        $break = 1;
                        $loop = 0;
                        break;
                    }
                }
                if($break==1) break;
            }
            echo $break;
        }
    

    Here I loop the Values in a Cloud and check if another Cloud contains the value. If I delete the current one and store all the other values into the matched cloud. Afterwards the loop will stop and another check starts. This is happening over and over again until no more matches are found.

    What do you think? Is there a nicer way? I guess I created an ugly monster. But I could find a better solution

    0 讨论(0)
  • 2021-01-27 16:22

    Use GROUP_CONCAT()

    SELECT user_id, GROUP_CONCAT(DISTINCT ip_address SEPARATOR ', ') 
    FROM TABLE_NAME GROUP BY user_id
    
    0 讨论(0)
  • 2021-01-27 16:22

    Taking the data from your example:

    +--------+---------+
    | userid | address |
    +--------+---------+
    | 1      | 12      |
    | 5      | 12      |
    | 1      | 13      |
    | 2      | 23      |
    | 9      | 23      |
    | 2      | 56      |
    | 4      | 56      |
    +--------+---------+
    

    for a table defined as

    CREATE TABLE table_27620030 (
        userid INTEGER,
        address INTEGER
    );
    

    the following query will list all userids that share the same address (and the address):

    SELECT address, GROUP_CONCAT(userid) userids
      FROM table_27620030
      GROUP BY address
      HAVING COUNT(DISTINCT userid) > 1
      ORDER BY address
    ;
    

    result:

    +---------+---------+
    | address | userids |
    +---------+---------+
    | 12      | 1,5     |
    | 23      | 2,9     |
    | 56      | 2,4     |
    +---------+---------+
    
    0 讨论(0)
提交回复
热议问题