2009-03-25 5 views
0

Так что я пример таблица называется пунктов со следующими столбцами:MySQL: несколько группировки

  • item_id (интермедиат)
  • person_id (интермедиат)
  • item_name (varchar)
  • item_type (varchar) - примеры: "ne WS», "событие", "документ"
  • item_date (DateTime)

... и стол человек со следующими столбцами: "person_id", "PERSON_NAME".

Я надеялся, что отображает список двух верхних отправителей (+ COUNT() отправленных товаров) за определенный период времени для каждого item_type. Вот в основном то, что я надеялся, что выход MySQL будет выглядеть следующим образом:

person_name | item_type | item_count 

Steve Jobs | document | 11 
Bill Gates | document | 6 
John Doe  | event  | 4 
John Smith | event  | 2 
Bill Jones | news  | 24 
Bill Nye  | news  | 21 

Как это возможно без отдельного запроса для каждого ITEM_TYPE? Заранее спасибо!

ответ

2
SELECT item_type, person_name, item_count 
FROM (
     SELECT item_type, person_name, item_count, 
       @r := IFNULL(@r, 0) + 1 AS rc, 
       CASE WHEN @_item_type IS NULL OR @_item_type <> item_type THEN @r := 0 ELSE 1 END, 
       @_item_type := item_type, 
     FROM (
       SELECT @r := 0, 
         @_item_type := NULL 
       ) vars, 
       (
       SELECT item_type, person_name, COUNT(*) AS item_count 
       FROM items 
       GROUP BY 
         item_type, person_name 
       ORDER BY 
         item_type, person_name, item_count DESC 
       ) vo 
     ) voi 
WHERE rc < 3 
+0

Насколько эффективна по сравнению с использованием отдельного запроса для каждого ITEM_TYPE? – Matt

+0

Это более эффективно. Если у вас много пар (item_type, person_name), это даже заметно эффективно. – Quassnoi

+0

Зависит от того, сколько элементов item_types у вас действительно есть, но делает одну поездку в базу данных, как правило, хорошая идея, и этот запрос выглядит так, что он не будет очень требовательным к ресурсу. –

1

Я думаю, что это нужно сделать, это:

SELECT person_name,item_type,count(item_id) AS item_count 
FROM person 
LEFT JOIN items USING person_id 
GROUP BY person_id 

Столбец «item_type» будет изворотливый, хотя каждая строка представляет собой несколько элементов, и вы только показывая item_type от одного из их. Вы можете перечислить все из них с помощью «GROUP_CONCAT», это очень весело.

+0

Вы просто группируетесь, но ему нужно только два лучших отправителя из каждого item_type. – Seb

+0

А, я не видел часть о 2-й категории в каждой категории. – GoatRider

1

Что-то вроде этого Шоул работы:

SELECT 
    p.person_name, i.item_type, COUNT(1) AS item_count 
FROM 
    person p 
    LEFT JOIN item i 
    ON p.person_id = i.person_id 
GROUP BY 
    p.person_id, 
    i.item_type 
HAVING 
    COUNT(1) >= (
    SELECT 
     COUNT(1) 
    FROM 
     item i2 
    WHERE 
     i2.item_type = i.item_type 
    GROUP BY 
     i2.person_id 
    LIMIT 1,1 
) 
+0

не работает: для некоторых типов событий возвращается только 1 верхний отправитель, даже если для этого типа больше. –

Смежные вопросы