Çok katmanlı MySQL sorgu?

2 Cevap php

Bir çok-çok bağlantı tablo ile iki tablo (girişleri ve etiketleri) var. Şu anda, benim kriterlerini karşılayan tüm girdileri almak için bir sorgu ve etiketleri almak için her giriş için bir sorgu yapıyorum.

Demek için bir yol olacağını, etiketleri ilk sorguda bir dizi olarak yeni bir sütun aracılığıyla geri döndü?

2 Cevap

Bu sorgu:

SELECT     e.id                               entry_id
,          GROUP_CONCAT(t.txt ORDER BY t.txt) tags
FROM       entry e
LEFT JOIN  entry_tag et
ON         e.id = et.entry_id
LEFT JOIN  tag t
ON         et.tag_id = t.id
GROUP BY   e.id

Virgülle ayrılmış bir liste olarak etiketleri dönecektir. Daha fazla seçenek için GROUP_CONCAT kadar okuyabilirsiniz: http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_group-concat

App oldukça kolay bir diziye bu genişletmek gerekir. Php Örneğin, kullanmak olabilir explode: http://php.net/manual/en/function.explode.php

Eğer tag veya entry_tag tablolardan daha fazla özelliklere ihtiyacınız varsa, henüz daha GROUP_CONCAT sütunları ekleyebilir, ya gibi (veri için bazı hale getirme biçimi düşünüyorum json) ve GROUP_CONCAT bu kullanmak, ya da sadece giriş başına birden çok satır dönmek ve birlikte girişleri ile etiketleri tutmak için uygulama sonuçlarını işleyebilir:

$sql = '
    SELECT     e.id                  entry_id
    ,          t.id                  tag_id
    ,          t.txt                 tag_text
    ,          t.published           tag_published
    FROM       entry e
    LEFT JOIN  entry_tag et
    ON         e.id = et.entry_id
    LEFT JOIN  tag t
    ON         et.tag_id = t.id
    ORDER BY   e.id
';        
$result = mysql_query($ql);
$entry_id = NULL;
$entry_rows = NULL;
while ($row = mysql_fetch_assoc($result)) {
    if ($entry_id != $row['entry_id']) {
        if (isset($entry_id)) {           //ok, found new entry
            process_entry($entry_rows);   //process the rows collected so far
        }
        $entry_id = $row['entry_id'];
        $entry_rows = array();
    }
    $entry_rows[] = $row;                 //store row for his entry for later processing
}
if (isset($entry_id)){                    //process the batch of rows for the last entry
    process_entry($entry_rows);           
}

Bir zamanlar birleştirilmiş bir dizeye olarak tüm etiketleri almak için GROUP_CONCAT function GROUP BY kullanabilirsiniz. http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html