2012-09-14 6 views
1

Я пытаюсь выбрать DISTINCT продуктов внутри категорий при помощи идентификаторами (1, 5, 12), упорядоченных по cat_order + prod_order из базы данных MySQLMySQL: SELECT, JOIN, GROUP BY запроса оптимизируя

Проблема:

если продукт находится в более чем 1-й категории Мне нужно, чтобы показать первый результат,

т.е. номер изделия 1 присваивается категории 1 и 5, мне нужно показать номер продукта 1 из 1 категории по с его prod_order и пропустить объявление в категории 5,

  • essentually Мне нужно отобразить все товары из категории 1, а затем перейти к категории 5 и отобразить все продукты там, где идентификатор продукта не был показан ранее, и перейти к другой категории в списке (12)

если я бегу что-то вроде:

SELECT 
    prod_to_cat.prod_id AS prod_to_cat_prod_id, 
    prod_to_cat.prod_order AS prod_to_cat_prod_order, 
    prod_to_cat.cat_id AS prod_to_cat_cat_id, 
    prod_to_cat.cat_order AS prod_to_cat_cat_order, 
    products.id, 
    products.name 

FROM 
    prod_to_cat, products 

WHERE 
    prod_to_cat.prod_id = products.id 
AND prod_to_cat.cat_id IN (1, 5, 12) 
GROUP BY 
    prod_to_cat.prod_id 
ORDER BY 
    prod_to_cat_cat_order ASC, 
    prod_to_cat_prod_order DESC 

Я получаю противоречивые результаты (продукт 1 не будет выбран из первой категории в списке), поэтому я решил выбрать без «GROUP BY prod_id "и оберните это другим выбором, чем группы prod_id.

так:

SELECT 
    prod_to_cat_prod_id, 
    prod_to_cat_prod_order, 
    prod_to_cat_cat_id, 
    name 
FROM 
    (
     SELECT 
      prod_to_cat.prod_id AS prod_to_cat_prod_id, 
      prod_to_cat.prod_order AS prod_to_cat_prod_order, 
      prod_to_cat.cat_id AS prod_to_cat_cat_id, 
      prod_to_cat.cat_order AS prod_to_cat_cat_order, 
      products.id, 
      products.name 
     FROM 
      prod_to_cat, products 
     WHERE 
      prod_to_cat.prod_id = products.id 
     AND prod_to_cat.cat_id IN (1, 5, 12) 
     ORDER BY 
      prod_to_cat_cat_order ASC, 
      prod_to_cat_prod_order DESC 
    ) AS prod 
GROUP BY 
    prod_to_cat_prod_id 
ORDER BY 
    prod_to_cat_cat_order ASC, 
    prod_to_cat_prod_order DESC 
LIMIT 0, 10; 

То, что я пытаюсь сделать:

Я пытаюсь найти более efficiant способ сделать это.

Структура таблицы:

prod_to_cat: 

prod_id | cat_id | cat_order | prod_order | 
    1  1   1   2 
    2  1   1   0 
    3  1   1   0 
    1  5   2   4 
    4  5   2   0 


products: 


id | name | descr | price | 
1 name_1 
2 name_2 
3 name_3 
4 name_4 

каждый продукт может быть в любом количестве категорий, например, идентификатор продукта 1 в категории ID 1 и 5 в приведенном выше примере.

Большое спасибо за любые ответы. Паша

+0

. , Вы понимаете, что ваши запросы группируются по одному полю (prod_id) и включают в себя другие столбцы. Это использует функцию MySQL, называемую скрытыми столбцами. Остальные столбцы берутся из произвольных записей внутри группы. В частности, prod_order имеет неуказанные значения, учитывая ваши данные. Скрытые столбцы предназначены для случая, когда все значения одинаковы. –

ответ

3

Вы хотите groupwise minimum:

SELECT prod_to_cat.*, 
     products.name 
FROM  prod_to_cat NATURAL JOIN (
      SELECT prod_id, 
        MIN(cat_id) AS cat_id 
      FROM  prod_to_cat 
      WHERE cat_id IN (1, 5, 12) 
      GROUP BY prod_id 
     ) t 
    JOIN products ON t.prod_id = products.id 
ORDER BY prod_to_cat.cat_order ASC, 
     prod_to_cat.prod_order DESC 

Посмотри на sqlfiddle.

+0

+1 для «группового минимума». –

+0

eggyal, большое спасибо за ваш ответ. - Выбор MIN (cat_id) не будет работать, так как список категорий не отсортирован, например, список категорий может быть: 5, 1, 12 в этом случае Мне нужно выбрать все продукты с 5, а затем перейти к 1 выбрать все продукты из 1, за исключением продуктов, которые были отображены в 5, чем перейти к 12 и т. Д. В любом случае - большое спасибо за ваш ответ! - Какие-нибудь другие предложения? – pasha

+1

@pasha: В этом случае замените 'MIN (cat_id)' на 'ELT (MIN (FIELD (cat_id, 1,5,12)), 1,5,12)'. Посмотрите на [sqlfiddle] (http://sqlfiddle.com/#!2/a3696/3/0). – eggyal