Использование производной таблицы и GROUP BY на 2 столбца на MySQL

0

Я использую экземпляр MySQL Server с определенными ограничениями (без CTE, неспособным создавать временные таблицы или даже новые таблицы), поэтому единственный способ разрешить его - использовать производные таблицы.

У меня есть следующая таблица t, содержащая каждый случай каждой продажи каждого месяца (1-12):

+------+-----------+-----------------+
|  id  |  product  |  sold_on_month  |
+------+-----------+-----------------+
|   1  | Product 1 |        1        |
|   2  | Product 1 |        2        |
|   3  | Product 1 |        2        |
|   4  | Product 1 |        3        |
|   5  | Product 1 |        3        |
|   6  | Product 1 |        4        |
|   7  | Product 1 |        4        |
|   8  | Product 1 |        4        |
|   9  | Product 1 |        4        |
|  10  | Product 1 |        4        |
|  11  | Product 2 |        1        |
|  12  | Product 2 |        1        |
|  13  | Product 2 |        2        |
|  14  | Product 2 |        2        |
|  15  | Product 2 |        3        |
|  16  | Product 2 |        3        |
+------+-----------+-----------------+

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

+-----------+---------+------------+
|  product  |  month  |  how_many  |
+-----------+---------+------------+
| Product 1 |    1    |     1      |
| Product 1 |    2    |     2      |
| Product 1 |    3    |     2      |
| Product 1 |    4    |     5      |
| Product 1 |    5    |     0      |
| Product 1 |    6    |     0      |
| Product 1 |    7    |     0      |
| Product 1 |    8    |     0      |
| Product 1 |    9    |     0      |
| Product 1 |   10    |     0      |
| Product 1 |   11    |     0      |
| Product 1 |   12    |     0      |
| Product 2 |    1    |     2      |
| Product 2 |    2    |     2      |
| Product 2 |    3    |     2      |
| Product 2 |    4    |     0      |
| Product 2 |    5    |     0      |
| Product 2 |    6    |     0      |
| Product 2 |    7    |     0      |
| Product 2 |    8    |     0      |
| Product 2 |    9    |     0      |
| Product 2 |   10    |     0      |
| Product 2 |   11    |     0      |
| Product 2 |   12    |     0      |
+-----------+---------+------------+

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

SELECT
  a.mn, COUNT(t.sold_on_month)
FROM
  (SELECT 1 AS mn UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
   UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) AS a
  LEFT JOIN t
    ON t.sold_on_month = a.mn
GROUP BY a.mn;

Итак, мне действительно нужен запрос, который использует одну и ту же производную таблицу для подсчета месяцев и группу по продукту и sold_on_month, показывая 0 в столбце how_many когда в этом месяце не было продано ни одного продукта. Помня, я не могу использовать CTE или временные таблицы.

Любая помощь приветствуется! :)

  • 1
    Совет 1: не хранить «Продукт». Совет 2: Рассмотрите возможность обработки проблем отображения данных (например, пропущенных результатов) в коде приложения.
  • 0
    Нет необходимости использовать подзапрос. Просто используйте SUM (how_many) и группируйте по продуктам и месяцам.
Теги:
count
group-by
derived-table

1 ответ

1
Лучший ответ

Создайте отдельный список продуктов с запросом. (Если у вас есть таблица продуктов, вы можете ссылаться на это.)

Учитывая только таблицу в вопросе, мы могли бы получить отдельный список, подобный этому

  SELECT q.product
    FROM t q
   GROUP
      BY q.product

Мы можем обернуть это в parens как встроенное представление (производную таблицу на языке MySQL), а затем выполнить перекрестное соединение с созданным списком месяцев,

SELECT p.product
     , a.mn
  FROM ( -- distinct list of products 
         SELECT q.product
           FROM t q
          GROUP
             BY q.product
       ) p
 CROSS
  JOIN ( -- list of months
         SELECT 1 AS mn UNION ALL ... 
       ) a
 ORDER
    BY p.product
     , a.mn 

И тогда мы можем добавить во внешнее соединение к t и выполнить GROUP BY и агрегировать в списке SELECT...

SELECT p.product
     , a.mn
  -- , IFNULL(SUM(t.qty),0)    AS tot_qty
     , COUNT(t.sold_on_month)  AS cnt_rows
  FROM ( -- distinct list of products
         SELECT q.product
           FROM t q
          GROUP
             BY q.product
       ) p
 CROSS
  JOIN ( -- list of months
         SELECT 1 AS mn UNION ALL ... 
       ) a
  LEFT
  JOIN t t
    ON t.product       = p.product
   AND t.sold_on_month = a.mn 
 GROUP
    BY p.product
     , a.mn
 ORDER
    BY p.product
     , a.mn

Если у вас есть другой источник для встроенного представления p, за исключением таблицы в вопросе (например, таблица продуктов с отдельным списком продуктов), мы могли бы ссылаться на это вместо этого.

Трюк - это CROSS JOIN между "месяцами" и "продуктами".

Затем внешнее соединение, чтобы получить соответствующие строки из t.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню