Усечение и объединение результатов mysql на основе количества результатов

#mysql #sql

#mysql #sql

Вопрос:

Я хотел бы объединить все названия элементов заказа; однако, если общее количество уникальных имен элементов превышает определенное число, тогда я хочу усечь каждое имя перед объединением имен. Ниже приведены условия:

Если общее количество уникальных имен элементов в заказе меньше 5, то используйте полное имя элемента и объедините имена; в противном случае, если общее количество уникальных имен элементов больше 5, то сократите каждое имя элемента до 20 символов и объедините усеченные имена. Например, ниже приведена моя таблица:

 order_id | item_name                           | item_name_len
---------|-------------------------------------|--------------   
1        | "pampers diapers ultra sensitive"   | 31  
1        | "cabbage salad pure organic greens" | 33
1        | "milky way"                         | 9
1        | "sea salt"                          | 8
1        | "cool waters fruit juice"           | 23
         |                                     |
2        | "pure clear glass crystals"         | 25
2        | "simple sugar edible paper"         | 25
  

Я хочу следующие результаты:

 order_id | all_item_names                           
---------|-----------------------------------------------------------
1        | "pampers diapers ultr ; cabbage salad pure o ; milky way ; 
         | sea salt ; cool waters fruit ju"
         |
2        | "pure clear glass crystals ; simple sugar edible paper"
  

Для заказа № 1, поскольку в заказе есть 5 уникальных имен элементов, мы сокращаем каждое из имен элементов до 20 символов и объединяем усеченные имена. Для заказа № 2, поскольку в заказе всего 2 уникальных имени элемента, мы берем полную длину имени и объединяем их. (Я включил название элемента strlen в таблицу выше для иллюстрации.)

Я пытаюсь использовать троичное условие, но оно не работает.
IF( COUNT(DISTINCT item_name) < 5, item_name, SUBSTRING(item_name, 1, 20) )

Смотрите запрос ниже. Я получаю Error code: 1111. Invalid use of group function

 SELECT
  w.order_id,
  (SELECT GROUP_CONCAT(  IF ( COUNT(DISTINCT o.item_name) < 5 , 
     o.item_name, SUBSTRING(o.item_name, 1, 20) ) ) separator ' ; ' )
    FROM order_items o WHERE o.order_id = w.order_id)AS all_item_names

FROM order_items w
GROUP BY order_id
  

Ответ №1:

Вы можете сделать это с помощью одной агрегации и без join :

 select oi.order_id,
       (case when count(*) < 5
             then group_concat(oi.item_name separator '; ')
             else group_concat(left(oi.item_name, 20) separator ';')
        end) as all_item_names
from order_items oi
group by oi.order_id
  

Ответ №2:

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

 select 
  o.order_id,
  group_concat(
    case 
      when counter < 5 then item_name
      else left(item_name, 20)
    end SEPARATOR ' ; '
  ) all_item_names 
from order_items o inner join (
  select
    order_id, count(*) counter
  from order_items
  group by order_id
) g on g.order_id = o.order_id
group by o.order_id
  

Смотрите демонстрацию
Результаты:

 | order_id | all_item_names                                                                            |
| -------- | ----------------------------------------------------------------------------------------- |
| 1        | pampers diapers ultr ; cabbage salad pure o ; milky way ; sea salt ; cool waters fruit ju |
| 2        | pure clear glass crystals ; simple sugar edible paper                                     |