2009-12-03 28 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

您能澄清一下您實際正在嘗試做什麼嗎? – 2009-12-03 02:26:23

+0

我試圖讓一組聯繫人看起來像他們可能重複到一個數組中。我改變了我的第二個查詢使用LIKE,但我仍然不確定這是否是最好的或最快的方式來完成它。將有可能有300,000或更多的記錄檢查。 'clientid' = \'13 \'AND'id'!= \''。$ rowNew ['id']。'\''。$ addQuery。' AND'fname' LIKE \'%'。addslashes($ rowNew ['fname'])。'%\'AND'lname' LIKE''''addslashes($ rowNew ['lname'])。'%\' – EricP 2009-12-03 04:10:22

回答

0

對於這樣的事情,你應該嘗試使用:

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

這確實在接觸自聯接基礎上的姓氏和名字,所以allC別名所有聯繫人的列表分享refC的名字和姓氏(包括他自己)。

這樣,您只需在一個SQL查詢中獲得所需的所有信息。通過在表contacts的列fnamelname上添加索引,可以在查詢上實現調整,因此聯接不必分析整個表以匹配。

--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' 

這是完全等同的(但IMO比更容易閱讀)到:

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 2009-12-03 08:54:35

+0

@Romain:「列的排序對代碼變得重要」......真的嗎?只有當你編寫代碼才能依靠訂單,當然。無論您是將其作爲關聯數組還是作爲對象獲取,訂單都不在這裏,也不在那裏。選擇*是不好的,因爲它可能檢索不需要的數據,IMO – Polsonby 2009-12-03 09:21:24

+0

我同意。但是,如果你將自己置於DBA的領導之下和/或期望你的查詢被其他人重新使用,那麼你可能想要考慮這些人在GPP上可能不那麼虔誠:) – Romain 2009-12-03 09:36:56

0

如果你只是想避免重複顯示,而不是真正從數據庫中刪除,使用DISTINCT SQL關鍵字。

+0

只是注意到查詢在那裏,但他已經評論了。 – Shiv 2009-12-03 02:10:39

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遍歷它。請注意,上面的「people」是由內部選擇創建的派生表的別名