MySQL: подзапрос к массиву? - PullRequest
3 голосов
/ 01 декабря 2010

Я работаю над небольшим сложным (по крайней мере для меня) запросом 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] => 
        )
)

Я хочу, чтобы элемент values ​​также стал массивом со всеми элементами в таблице значений, которые совпадают (WHERE productValues.product = product.id).

Что я делаю неправильно?

Ответы [ 4 ]

8 голосов
/ 01 декабря 2010

Я не уверен, что вы можете вернуть подобные подзапросы. Решением будет использование GROUP_CONCAT в вашем подзапросе для объединения всех значений в строку. Затем в результате вы можете разделить эту строку на массив, используя explode.

обновление: подзапрос может соответствовать только 1 строке
Источник: http://dev.mysql.com/doc/refman/5.0/en/subquery-errors.html

4 голосов
/ 01 декабря 2010
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;

дает таблицу с одной строкой для каждого значения pv.value (кстати, использование зарезервированных слов, таких как «значение», не рекомендуется).Упорядочение вывода по 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'];
}

Структура, которую я дал, возможно, более гибкая, чем та, которую вы запрашивали, в том смыслепозволяет получить доступ к определенному продукту через ключ массива.

1 голос
/ 01 декабря 2010

MySQL может возвращать только двумерный набор результатов, он не может возвращать более сложную структуру данных. Вам нужно будет сделать два отдельных запроса и присоединить результат к вашему приложению.

Пример в 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']);
}
?>

Удачи!

1 голос
/ 01 декабря 2010

Я думаю, что атрибут 'values' всегда будет одной переменной.Подумайте, чистый SQL, независимо от PHP - если бы вы запустили такой запрос в редакторе SQL - вы бы получили атрибут values ​​в виде одного столбца.Если бы вы попросили восстановить более одного столбца, вы бы получили ошибку.В общем, запросы SQL всегда плоские - один уровень.Мое предложение - запустить 2 запроса и соединить их в слой PHP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...