SQL sorgu birbirleriyle ilgili 2 tablolardan kayıtları çekmek için - Tablo 1 bağlı Tablo 2

2 Cevap php

Ben 2 tablolar var. Tablo 1 'haberler' ve Tablo 2 'article_categories' dir. Bir kullanıcı bir makale oluşturduğunda, bu makalelerde 'içine saklanır. Kullanıcı, makale oluştururken bu makalede görünebilir altında çeşitli kategoriler seçebilirsiniz. Şu anda, bir makale (ileride artabilir) 10-25 kategorilerden herhangi bir yere ait seçilebilir. Makale yayımlandı altında, bu kategorileri, 'article_categories' saklanır. Yani bu, tek bir makalenin kimlik tablo 'article_categories' birden fazla ilgili değerleri olabilir anlamına gelir. Her iki tablodan tüm değerlerin çekilmesi, ben çekilmesine ve değerler bir dizi saklanacak 'article_categories' dan tüm değerleri gerekir.

Benim sorum bunu yapmak için kullanmak ne SQL sorgusu hakkında? Ben İç katılın kullanmalı mıyım, Sol dış birleşim, Katıl ...? Ne yapmak için en iyi yol olacağını? Ben bu phpmyadmin katılır bazı denemek yaptım ve onlar bana aslında, yazı sadece bir kez ve tüm ilgili kategoriler getirilecek getirilecek gerektiğini, aynı makalede, yinelenen değerleri verir. Bunu gerçekleştirmek için 2 farklı içine sorguyu bölmek zorunda kalmadan tüm aynı sorguda bunu yapmak istiyordu. Senin için kolay, böylece benim tablo yapıları bağlama am:

CREATE TABLE IF NOT EXISTS `articles` (
  `article_id` int(11) unsigned NOT NULL auto_increment,
  `creator_id` int(11) unsigned NOT NULL,
  `article_title` varchar(150) NOT NULL,
  `article_status` varchar(10) NOT NULL,
  PRIMARY KEY  (`article_id`),
  KEY `buyer_id` (`creator_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

--
-- Dumping data for table `articles`
--

INSERT INTO `articles` (`article_id`, `creator_id`, `article_title`, `article_status`) VALUES
(1, 1, 'My article 1', 'Pending');


CREATE TABLE IF NOT EXISTS `article_categories` (
  `article_id` int(11) unsigned NOT NULL,
  `category_id` smallint(3) unsigned NOT NULL,
  PRIMARY KEY  (`article_id`,`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `article_categories`
--

INSERT INTO `article_categories` (`article_id`, `category_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
(1, 4),
(1, 5),
(1, 36),
(1, 71);

Ayrıca ben article_categories tabloda article_id ve category_id tuşları üzerinde bir bileşik anahtar olduğunu lütfen unutmayın. Ben kullanılan bir örnek sorgu aşağıdaki gibidir:

SELECT *
FROM articles, article_categories 
WHERE articles.article_id = article_categories.article_id
AND articles.article_id = 1;

Bu sonuçları:

article_id  creator_id	article_title	article_status	article_id	category_id
    1   1	My article 1	Pending	1	1
    1   1	My article 1	Pending	1	2
    1   1	My article 1	Pending	1	3
    1   1	My article 1	Pending	1	4
    1   1	My article 1	Pending	1	5
    1   1	My article 1	Pending	1	36
    1   1	My article 1	Pending	1	71

Görülebileceği gibi, makaleler tablosundan değer yinelenen ve o (o biçimlendirme berbat durumda, son sütun var) aynı zamanda tüm kategoriler almak mümkün bulunuyor. Ben bir dizide bu döngüye değerler eklemek ve benim işleme devam böylece, yalnızca bir kez makaleler tablosundan değerleri almak ve bir döngü içinde category_id olsun istedim. Bu yukarıdaki değerleri getiriliyor sonra ne yapmak niyetinde olduğunu:

<?php
//i wanted to check if the article_id exists before i pull the related categories. 
//If I do it this way and output using mysql_num_rows, it gives me value 7,
//when in fact, the there's only 1 article with such Id. This means it also counts
//  the number of categories. Is there a way to uniquely identify only the number of
// articles (just to see if it exists or not, in the place)

$result = mysql_query("SELECT *
FROM articles, article_categories 
WHERE articles.article_id = article_categories.article_id
AND articles.article_id = 1");

while ( $rows = mysql_fetch_array($result) )
    {	//i don't think this the following 2 assignments should be done in the loop
    	$article_id = $rows['article_id'];
    	$article_title = $rows['article_title'];

    	//(loop all the category_id from the 2nd table and add to the array below)
    	$categories_id[] .= ??????? --> How do i do this?		
    }	

?>

Tüm kategori kimliklerini almak için benim yeteneğini sınırlamak gibi Açıkçası, ben yukarıdaki bir LİMİTİ 1 yapamaz.

Yani benim soru (ben fark yok nasıl (bir döngüde) 2. tablosundan tüm category_id alabilirim olması ve diziye eklemek ve aynı zamanda tablo 1 değerleri sadece bir kez getirilen emin olun ki Tablo 1 den getirilen değerleri aynı ama) onlara döngü mantıklı değil. Bunu başarmak için, ben tür Ben maksimum verimlilik ile sorguyu yürütmek için kullanın ve DB üzerinde hit aza indirmek için tek bir sorguda asgari kaynakları, tüm kullanmalısınız tarihi ne giriş almak istiyorum. Ben mantıklı umuyoruz.

Şimdiden teşekkürler.

2 Cevap

EDIT:

SELECT articles.article_id, articles.article_title, GROUP_CONCAT(article_categories.category_id SEPARATOR ',') as category_id
FROM articles
LEFT JOIN article_categories ON  (articles.article_id = article_categories.article_id)
-- WHERE CLAUSE IF YOU WANT/NEED --
GROUP BY articles.article_id;

EDIT: Added column alias for group concat GROUP_CONCAT(article_categories.category_id SEPARATOR ',') as category_id

<?php
$result = mysql_query("SELECT articles.article_id, articles.article_title, GROUP_CONCAT(article_categories.category_id SEPARATOR ',') as category_id
FROM articles, article_categories
WHERE articles.article_id = 1
GROUP BY articles.article_id;");

while ( $rows = mysql_fetch_array($result) )
    {   
        $article_id = $rows['article_id'];
        $article_title = $rows['article_title'];

        //(loop all the category_id from the 2nd table and add to the array below)
        $categories_id = explode(',', $rows['category_id']);               
    }   

?>

O sınırı var sanki grup concat dikkat:

The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024. The value can be set higher, although the effective maximum length of the return value is constrained by the value of max_allowed_packet.

EDIT: Also without using the group concat i would go ahead and do it the way you had it... just make the category id your primary looping stcuture:

<?php
$result = mysql_query("SELECT articles.article_id, articles.article_title, article_categories.category_id
FROM articles, article_categories
WHERE articles.article_id = 1");

$articles = array();
while ( $rows = mysql_fetch_array($result) )
    {   
        if(!array_key_exists($rows['article_id'], $articles)
        {
           $articles[$rows['article_id']] = array(
               'article_id' => $rows['article_id'],
               'article_title' => $rows['article_title']
               'categories_id' => array()
            );
         }

         $articles[$rows['article_id']][] = $rows['categories_id'];             
    }   

?>

Bu şekilde sadece bir kez sorgulamak, bur sonra Yazıların veri çalışması için yazı üzerinde döngü gerekir.

Eğer açıklayan bu çok-çok senaryoda, sizin olsun set, tek bir sonuca yinelenen verileri kaçınamaz.

İşte bir fikir. Dizi indeksi gibi kendi veritabanı tuşu ile kategori isimlerinin bir dizi oluşturmak için ayrı bir sorgu yapmak.

$sql = "SELECT category_id, category_name FROM Categories";
$result = mysql_query($sql);
$arrCategories = array();
while ( $row = mysql_fetch_assoc($result) {
    $arrCategories[$row['category_id']] = $row['category_name'];
}

Şimdi, bir dizideki tüm kategorilerin isimleri var.

Eğer makaleleri seçerken, size katılmak tablosundan category_ids çeker ayrı bir sorgu yapmak gerekecek. Eğer makale kimlikleri ve ilgili kategorilerin bir listesini elde etmek için iki boyutlu bir dizi kullanabilirsiniz

$arrArticleCategoryIds = array();

$result = mysql_query("SELECT *
FROM articles, article_categories 
WHERE articles.article_id = article_categories.article_id
AND articles.article_id = 1");

while ( $rows = mysql_fetch_array($result) )
    {   
        // why bother doing this when you've already hard-coded "1"?
        $article_id = $rows['article_id'];
        $article_title = $rows['article_title'];

        //(loop all the category_id from the 2nd table and add to the array below)
        // $categories_id[] .= ??????? --> How do i do this?               

        // here's how:
        $sql = "SELECT category_id 
                FROM `article_categories` 
                WHERE article_id = $article_id
        ";
        $category_id_results = mysql_query($sql);

        while ( $category_id_row = mysql_fetch_assoc($category_id_results) ) {
            $arrArticleCategoryIds[$article_id][] = $row['category_id'];
       }

    }

İki dizilerle gireriz:

$arrCategories 
Array
(
    [1] => apple
    [2] => banana
    ...
)

$arrArticleCategoryIds
Array
(
    [1] => Array
        (
            [1] => 13
            [2] => 9
         )
    [3] => Array
         (
            [1] => 5
            [2] => 7
         )
    )
)

'1 'Ve '3' makale kimlikleri, ve 13, 9, 5, 7 ve onlar altında bulunan konum makale id ait kategori kimlikleri vardır nerede.