Yinelenen satırları neden birçok bağlantı masaya One döndü

3 Cevap php

Ben şimdiye kadar gördüğüm her şey otomatik olarak bir veritabanında yinelenen girdileri kaldırma ile ilgili. Ben veritabanında bu o there is no duplicate data başında vurgulamak istiyorum. Ben de hala çok RDBMS tasarım, normalleşme, ilişkiler, ve, en önemlisi, SQL öğrenmeye olduğum gerçeği ile başlayacağız!

Ben bir ClientID (PK) ve bir CLIENT_NAME ile, müşterilerine bir tablo var. Ben bir roleID (PK) ve bir ROLE_NAME ile, rollerin bir tablo var. Herhangi bir müşteri ile ilişkili birden fazla rolleri olabilir. Yani ClientID ile, bir client_role_link tablo oluşturulur ve iki alanları olarak roleID. Sonra bu çalıştırın:

SELECT client.client_name, role.role_name FROM client 
  LEFT JOIN client_role_link ON client_role_link.clientid=client.clientid 
  LEFT JOIN role ON client_role_link.roleid=role.roleid 
  WHERE (role.roleid='1' OR role.roleid='2')

Yani ben onunla ilişkili iki rol (roller '1 've '2') olan bir müşterim var diyelim. Bu sorgu, iki satır, her rol için birini döndüren. Ben bu sonuçları elde zaman geri bir while sonuçlarına dolaşmak için döngü ve bir <select> liste haline çıkış onları kullanıyorum. Daha sonra listede aynı müşteri ile iki <option> 'nin neden oluyor.

Benim sorgu iki satır dönüyor anlıyorum, bu mantıklı. Yani burada iki kat soru geliyor:

  1. Ben kullanarak gereken iyi bir veritabanı / tablo tasarım, ya da bir daha optimize sorgu var mı?
  2. Ya da bu ben PHP işlemesi gereken bir şeydir? Eğer öyleyse, dizi üzerinden geri döngü ve çiftleri kaldırarak sonra, bir diziye tüm sonuçlar ekleyerek daha zarif bir çözüm var mı?

Düşünceler?

3 Cevap

Hem rolleri göstermek istiyorsanız, o zaman sorgu OK.

MySQL dizisi veritiplerini desteklemiyor, bu yüzden yinelenen istemci adları ile resultset kullanarak PHP tarafında bir ilişkisel dizi doldurmak gerekir.

Sadece roller birine sahip olan müşterilerine göstermek gerekiyorsa, bu sorguyu kullanabilirsiniz:

SELECT  c.*
FROM    client c
WHERE   c.clientid IN
        (
        SELECT  roleid
        FROM    client_role_link crl
        WHERE   crl.roleid IN (1, 2)
        )

Bu istemci başına bir kayıt dönecektir, ancak herhangi bir rol göstermez.

Üçüncü yol sunucu tarafında rol isimleri implode olacaktır:

SELECT  c.*, GROUP_CONCAT(role_name SEPARATOR ';') AS roles
FROM    client c
LEFT JOIN
        client_role_link crl
ON      crl.clientid = c.clientid
        AND crl.roleid IN (1, 2)
LEFT JOIN
        role r
ON      r.roleid = crl.roleid
GROUP BY
        c.id

ve PHP tarafta onları patlayabilir, ama emin olun rol adları ayırıcı ile karıştırmayın olmaz olun.

Sen client_name alanında GROUP BY yan tümcesi ile toplama SQL işlevi group_concat () kullanabilirsiniz. Bu rolleri ile bir virgülle sınırlandırılmış bir dize içeren tek bir satır ile bir sonuç kümesi döndürür.

PHP Eğer () bu dizeyi patlayabilir ve yerine satır satır getiriliyor çıkan dizi üzerinden yineleme.

Sen mysql_fetch_assoc() arka dizisi şeklinde onları almak için kullanabilirsiniz. Sonra bir şey olabilir gibi code untested, but may work:

$sql = "SELECT client.id, client.client_name, role.role_name FROM client LEFT JOIN client_role_link ON client_role_link.clientid=client.clientid LEFT JOIN role ON client_role_link.roleid=role.roleid WHERE (role.roleid='1' OR role.roleid='2')";
$result = mysql_query($sql);
$res = array();
while ($row = mysql_fetch_assoc($result)) {
    $res[$row['id']]['roles'][] = $row['role_name'];
    $res[$row['id']]['client_name'] = $row['client_name']; //you'll be overwriting each iteration probably a better way
}