2010-12-01 41 views
2

サブクエリを含んだ(少なくとも私のための)わずかな複雑さのmySQLクエリに取り組んでいます。正直ではありません。mySQL:サブクエリから配列へ?

SELECT `products`.`id`, `product`.`price`, 
    (SELECT `value` FROM (`productValues`) 
    WHERE `productValues`.`product` = 'product.id' 
) as values 
FROM (`products`) WHERE`product`.`active` = 1 

現在の結果は以下のようになります。

Array 
(
    [0] => Array 
     (
      [id] => 1 
      [active] => 1 
      [price] => 1000 
      [values] => 
     ) 
) 

私が欲しいものも(WHERE productValues.product = product.id)に一致する値テーブル内のすべての要素を持つ配列になるための値要素です。

私は間違っていますか?

答えて

3
SELECT p.id, p.price, pv.`value` 
FROM products p 
    JOIN productValues pv 
    ON p.product_id=pv.product 
WHERE p.active = 1 
ORDER BY p.id; 

(BTW、「値」のような予約語を使用することは推奨されない)各pv.valueに対して1つの行を有する表を与えます。 p.idによる出力の順序は、特定の製品のすべての行が確実に一致するようにします。したがって、アプリケーション層では、行をループし、p.idが変更されるたびに製品を変更します。

$old_id=NULL; 
$datastructure=array(); 
while($arr=$result->fetch_assoc()){ 
    if($arr['id']!=$old_id){ 
    $datastructure[$arr['id']][price]=$arr['price']; 
    $old_id=$arr['id']; 
    } 
    $datastructure[$arr['id']]['values'][]=$arr['value']; 
} 

私が与えてくれた構造は、それが配列のキーによって、特定の製品にアクセスすることができますようにあなたが尋ねたものよりもおそらくもっと柔軟性があります。

5

このようなサブクエリを返すことができるかどうかはわかりません。解決策は、サブクエリにGROUP_CONCATを使用して、すべての値を文字列に連結することです。結果として、この文字列をexplodeを使用して配列に分割できます。

更新:サブクエリが唯一の1行
ソース一致させることができます:http://dev.mysql.com/doc/refman/5.0/en/subquery-errors.html

+0

これは、 'GROUP_CONCAT'が文字列<= 255文字を生成することが保証されている場合にのみ妥当な解決策です。それ以外の場合、値は切り捨てられます。 – dnagirl

+1

@dnagirl - 'group_concat_max_len'のサイズをいつでも増やすことができます。' group_concat'は便利です。結果を反復するコードを書く必要がないので、できるだけ早くmysqlの結果を解放することができます。 – ajreal

+0

@ajreal: 'GROUP_CONCAT'は便利です。しかし、 'group_concat_max_length'を変更しても、制限はまだ存在し、その制限はあなたに噛み付く可能性があります。私はそれを証明するTシャツを持っています。 ;) – dnagirl

0

を私は「値」属性は、常に1つの変数になると思います。 PHPに関係なく、純粋なSQLを考えてみましょう.SQLエディタのようなクエリを実行していれば、値属性を1つの列として取得できます。複数の列を取得するように求めていた場合は、エラーが発生していました。
一般に、SQLクエリは常にフラットです(1つのレベル)。
私の提案 - 2つのクエリを実行し、それらをPHPレイヤーにまとめます。

1

MySQLは2次元の結果セットしか返せません。より複雑なデータ構造を返すことはできません。 2つの別々のクエリを作成し、アプリケーションで結果を結合する必要があります。 PHPで

例:

<?php 

//getting a list of products 
$result = mysql_query("SELECT `products`.`id`, `product`.`price` 
         FROM (`products`) 
         WHERE`product`.`active` = 1"); 

$product_ids = array(); 
$products = array(); 
while($r = mysql_fetch_assoc($result)) 
{ 
    $products[$r['id']] = $r; 
    $product_ids[] = $r['id']; 
} 

$comma_separated_ids = implode(",", $product_ids); 

//getting a list of all product values for given products 
$result = mysql_query("SELECT `value`, `product` 
         FROM (`productValues`) 
         WHERE `productValues`.`product` IN ('$comma_separated_ids')"); 

//joining them together 
while($r = mysql_fetch_assoc($result)) 
{ 
    if (!isset($products[$r['product']]['values'])) 
     $products[$r['product']]['values']; 

    $products[$r['product']]['values'][] = $r['value']; 
} 

?> 

GolezTrolの回答に基づいて、もう少しエレガントバリアント:

<?php 
$result = mysql_query("SELECT `products`.`id`, GROUP_CONCAT(`productValues`.`value`) AS `values` 
         FROM `products`, `productValues` 
         WHERE`product`.`active` = 1 AND `productValues`.`product` = `products`.`id` 
         GROUP BY `products`.`id`"); 

$products = array(); 
while($r = mysql_fetch_assoc($result)) 
{ 
    $products[$r['id']] = $r; 
    $products[$r['id']]['values'] = explode(',', $products[$r['id']]['values']); 
} 
?> 

幸運!

関連する問題