Помогите составить запрос

Есть 3 таблицы: категории, товары, варианты.

категории

id | cat_name
1 | телефоны
2 | ноутбуки
3 | телевизоры

товары

id | product_name | cat_id
1 | galaxy s3 | 1
2 | philips | 3
3 | xperia | 1
4 | lenovo | 2
5 | chromebook | 2

варианты

id | variant_name | variant_price | product_id
1 | зеленый | 120 | 5
2 | красный | 150 | 5
3 | синий | 70 | 5
4 | серый | 200 | 2
5 | зеленый | 130 | 4
6 | черный | 250 | 3
7 | белый | 300 | 1

Задача: вывести список категорий, товаров в каждой категории и варианты каждого товара.

Скрытый текст
Телефоны
    galaxy s3
        белый - 300
    xperia
        черный - 250

Ноутбуки
    lenovo
        зеленый - 130
    chromebook
        зеленый - 120
        красный - 150
        синий - 70

Телевизоры
    philips
        серый - 200



Сейчас код выглядит так:
$query = query('SELECT FROM * категории');
while ($res = array($query)){
    echo $res[cat_name];

    $query2 = query('SELECT * FROM товары WHERE catid=$res[id]');
    while ($res2 = array($query2)){
        echo $res2[product_name];

        $query3 = query('SELECT * FROM варианта WHERE product_id=$res2[id]');
        while($res3 = array($query3)) {

            echo $res3[variant_name];

        }

    }

}


Естественно это генерирует массу запросов. Можно ли как-то сделать выборку 1 запросом?
  • Вопрос задан
  • 3256 просмотров
Решения вопроса 1
truekenny
@truekenny
<?
$sql = <<< TXT
	SELECT
		cats.id as catsid, prod.id as prodid, cats.cat_name, prod.product_name, vars.variant_name
	FROM категории cats, товары prod, варианты vars
	WHERE
		cats.id = prod.cat_id
		AND prod.id = vars.product_id
	ORDER BY cats.id, prod.id
TXT;

...

$cat_id = -1;
$prod_id = -1;
foreach( ... as $line){
	if($cat_id != $line['catsid']){
		$cat_id = $line['catsid'];
		$prod_id = -1;
		echo $line['cat_name'], "\n";
	}
	if($prod_id != $line['prodid']){
		$prod_id = $line['prodid'];
		echo "\t", $line['product_name'], "\n";
	}
	echo "\t\t", $line['variant_name'], "\n";
}

Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
UZER2006
@UZER2006
В таком виде, как нужно вывести – нельзя. Можно сделать два JOIN'а, вытянуть все данные (опционально отфильтрованные по кодам категорий и товаров), а потом через foreach сформировать массив с нужной структурой (или, если выборка с сортировкой, сразу выводить, вставив внутрь foreach нужные if'ы).
Но в случае больших объёмов данных нужно искать середину между количеством запросов и количеством данных за один запрос. Например, вытянуть категории и в цикле для каждой вытаскивать товары с вариантами.
Ответ написан
Комментировать
sevka_fedoroff
@sevka_fedoroff
Я так понял, вы в sql новичок? Запрос примерно такой:
select * from категории, товары, варианты where варианты.product_id = товары.id and товары.cat_id = категории.id

Но имена категорий и товаров будут повторяться. Как сказано выше, вам нужно будет уже в php позабодиться о том, чтобы правильно вывести данные. Однако следует помнить, что для производительности зачастую лучше несколько легких запросов чем один тяжелый.
Ответ написан
@artishok Автор вопроса
кратко
Вопрос задавал перед уходом и немного напутал структуру. Там есть еще 1 таблица, из-за чего у 2 из 3 таблиц из вопроса в запросе join к этой 4-ой таблице.

За пример взял запрос truekenny, и перебрав несколько вариантов, получил то что надо.
В оригинале у меня есть еще группировка, а в получившемся запросе обошелся без неё, только сортировка.

Время выполнения обоих вариантов примерно одинаково. Надо попробовать еще вариант, который написал UZER2006 в последнем предложении.
В общем протестирую еще немного и переберу варианты.

sevka_fedoroff, join'ы составлять умею, а с остальным не сталкивался

Спасибо всем кто помог
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы