2009-12-03 3 views
0

Я написал код для выбора дубликатов и группировки с использованием имени и фамилии. Я собираю их в многомерном массиве и дедуплируют/объединяют их, используя jQuery/Ajax на полученной странице. Я хотел бы спросить, есть ли лучший способ создания массива, чем то, как я это делаю. Вот мой код. Спасибо.Выберите дубликаты с PHP и MySql для процесса слияния

$dataArr=fetchDups($conn, 13, 5); // get a few at a time 

print '<div style="clear:both;"></div><pre>'; 
print_r($dataArr); 
print '</pre><div style="clear:both;"></div>'; 


    function fetchDups($conn, $client_id, $limit='') 
    { 

    $sql=' SELECT * FROM `contacts` WHERE `clientid`=\'13\' GROUP BY fname, lname '; 
    //$sql=' SELECT DISTICT fname, lname, * FROM `clients` WWHERE `clientid`=\'13\' '; 
    $res=mysql_query($sql, $conn)or die(mysql_error()); 
    $contactsRow=array(); 
    while($row=mysql_fetch_array($res)){ 
     echo $row['fname'].'<br>'; 
     $contactsRow[]=$row; 
    } 

    mysql_freeresult($res); 

    $dataArr=array(); 
    $i=0; 
    $limitNum=0; 
    //---------------------------------- 

    foreach($contactsRow AS $rowNew){ 

    $sql=' SELECT * FROM `contacts` WHERE `clientid`=\'13\' AND `id`!=\''.$rowNew['id'].'\' 
    AND (`fname` = \''.$rowNew['fname'].'\' OR `lname` = \''.$rowNew['lname'].'\') 
    '; 
    //echo $sql; 
    $res=mysql_query($sql, $conn)or die(mysql_error()); 
    $rowCountDup=mysql_num_rows($res); 

    if($rowCountDup>0){ 

    $d=0; 
    $dataArr[$i]=array(); 
    $dataArr[$i][$d]=$rowNew; 
    while($rowNew=mysql_fetch_array($res)){ 
    $dataArr[$i][($d+1)]=$rowNew; 
    $d++;  
    } 

    $i++; 
    $limitNum++;  

    } 

    // limit the results. too many crashes the browser 
    if($limitNum==$limit){ 
    break; 
    } 

    } 

    mysql_freeresult($res); 

    return $dataArr; 

    } 
+0

Можете ли вы пояснить, что вы на самом деле пытаетесь сделать? –

+0

Я пытаюсь получить группы контактов, которые выглядят так, как будто они могут быть дублирующими в массив. Я изменил свой второй запрос на использование LIKE, но я все еще не уверен, что это лучший или самый быстрый способ сделать это. Для проверки будет возможно 300 000 или более записей. 'clientid' = \ '13 \' AND' id'! = \ ''. $ RowNew ['id']. '\' '. $ AddQuery.' И 'fname' LIKE \ '%'. Addlashes ($ rowNew ['fname']). '% \' AND' lname' LIKE \ '%'. Addslashes ($ rowNew ['lname']). '% \' – EricP

ответ

0

Для такого рода вещей, вероятно, вы должны попробовать использовать:

SELECT * FROM contacts refC JOIN contacts allC USING (fname, lname) WHERE refC.clientid='13'

Это делает автообъединение на контактах на основе имени и фамилии, поэтому allC псевдонимов в список всех контактов, доля refC - фамилия и имя (включая самого себя).

Таким образом, вы получаете всю информацию, которую ищете, только в одном запросе SQL. Настройка может быть достигнута в запросе путем добавления индекса в столбцах fname и lname таблицы contacts, поэтому для объединения не нужно разбирать всю таблицу, чтобы она соответствовала.

--edit: Вы можете получить, чтобы определить более точно, как вы присоединиться к вашей таблицы, как, например:

SELECT * 
FROM contacts refC 
JOIN contacts allC ON (allC.fname LIKE CONCAT(refC.fname, '%') AND allC.lname LIKE CONCAT(refC.lname, '%')) 
WHERE refC.clientid='13' 

Который строго эквивалентен (но ИМО легче читать, чем), чтобы:

SELECT * 
FROM contacts refC,contacts allC 
WHERE allC.fname LIKE CONCAT(refC.fname, '%') 
AND allC.lname LIKE CONCAT(refC.lname, '%') 
AND refC.clientid='13' 
+0

Забыл упомянуть ... Есть много причин, по которым не рекомендуется «SELECT *», мой фаворит в том, что он вызывает слишком много связи между логикой приложения и структурой базы данных (упорядочение столбцов становится важным для кода, тогда как не должны). – Romain

+0

@Romain: «упорядочение столбцов становится важным для кода» ... Действительно? Только если вы напишете свой код, чтобы полагаться на заказ, конечно. Получаете ли вы его как ассоциативный массив или как объект, порядок не существует ни здесь, ни там. Select * is bad только потому, что он потенциально извлекает ненужные данные, IMO – Polsonby

+0

Я согласен. Но если вы ставите себя в голову администратора базы данных и/или ожидаете, что ваши запросы будут повторно использоваться другими людьми, вы можете подумать, что эти люди не могут быть настолько религиозными на GPP :) – Romain

0

Если вы просто хотите, чтобы избежать отображения дубликатов и фактически не удаляя их из БД используйте DISTINCT SQL ключевое слово.

+0

только что заметил, что запрос есть, но он прокомментировал это. – Shiv

0

Или вы могли бы попробовать что-то вроде второго запроса здесь, который использует производную таблицу:

mysql> select * from contacts ; 
+----+--------+---------+ 
| id | fname | lname | 
+----+--------+---------+ 
| 1 | Annie | Haddock | 
| 2 | Annie | Haddock | 
| 3 | Ginger | Mole | 
| 4 | Ted | Ted  | 
| 5 | Ted | Ted  | 
+----+--------+---------+ 
5 rows in set (0.01 sec) 

mysql> select id, fname, lname, total from 
      (select *, count(*) as total 
       from contacts group by fname, lname) people 
     where total > 1; 
+-----------+--------------+--------------+--------------+ 
| people.id | people.fname | people.lname | people.total | 
+-----------+--------------+--------------+--------------+ 
| 1   | Annie  | Haddock  | 2   | 
| 4   | Ted   | Ted   | 2   | 
+-----------+--------------+--------------+--------------+ 
2 rows in set (0.01 sec) 

то просто итерации через него с помощью foreach. Обратите внимание, что «люди» выше - это псевдоним для производной таблицы, созданной внутренним выбором.