MySQL: возврат сгруппированных полей, где группа не пуста, эффективно - PullRequest
1 голос
/ 26 мая 2010

В одном утверждении я пытаюсь сгруппировать строки одной таблицы, соединяя ее с другой таблицей. Я хочу получать сгруппированные строки, в которых их сгруппированный результат не пуст.

Ex. Предметы и категории

SELECT Category.id
FROM Item, Category
WHERE Category.id = Item.categoryId
GROUP BY Category.id
HAVING COUNT(Item.id) > 0

Приведенный выше запрос дает мне результаты, которые мне нужны, но это медленный процесс, поскольку он должен учитывать все строки, сгруппированные по Category.id.

Какой более эффективный способ?

Я пытался выполнить Группу по LIMIT, чтобы получить только одну строку на группу. Но мои попытки ужасно провалились. Есть идеи, как мне это сделать?

Спасибо

Ответы [ 4 ]

0 голосов
/ 26 мая 2010

Я думаю, и это только мое мнение, что правильный подход - это считать все вещи. Может быть, проблема в другом месте.

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

SELECT categoryid, COUNT(*) FROM Item GROUP By categoryid

Это даст вам хэш со всеми предметами по категориям. Но это не будет включать пустые категории.

Затем для получения информации о категориях выполните следующее:

SELECT category.* FROM category
INNER JOIN (SELECT categoryid, COUNT(*) AS n FROM Item GROUP By categoryid) AS item
ON category.id = item.categoryid
0 голосов
/ 26 мая 2010

Как насчет удаления таблицы категорий, если она вам не нужна?

SELECT Item.categoryId 
FROM Item
GROUP BY Item.categoryId

Я не уверен, что вам даже нужно предложение HAVING, поскольку, если в категории нет элемента, он не будет создавать группу.

0 голосов
/ 26 мая 2010

Я думаю, что это функционально эквивалентно (возвращает каждую категорию, содержащую хотя бы один элемент) и должно быть намного быстрее.

SELECT 
  c.id
FROM 
  Category c
WHERE
  EXISTS (
    select 1 from Item i where i.categoryid = c.categoryID
  )
0 голосов
/ 26 мая 2010

Попробуйте это:

SELECT  item.categoryid
FROM    Item
JOIN    Category
ON      Category.id = Item.categoryId
GROUP BY
        item.categoryid
HAVING  COUNT(*) > 0

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

Если вы хотите выбрать непустые категории, сделайте следующее:

SELECT  category.id
FROM    category
WHERE   id IN
        (
        SELECT  category_id
        FROM    item
        )

Чтобы это работало быстро, создайте индекс для item (category_id).

...