Как добавить нулевое значение в group_concat, если запись не существует?

У меня есть этот SQL-запрос с substring_index и group_concat, но результаты, которые я получаю, не дают правильного местоположения значений, потому что значения не существуют.

Мне нужно добавить нулевое или нулевое значение, чтобы иметь правильное расположение значений в результате sql.

В столе есть три крышки (1, 2, 3). Крышка должна быть базовым счетчиком P (P1, P2, P3) для substring_index.

Это таблица:

lid   class_id   class          total   
-----  -------    -----        -----   
  1     73       Leader         10000      
  1     77       Consultant     8000       
  1     83       Coordinator    6000       
  2     73       Leader         20000      
  2     76       Staff          8000       
  2     77       Consultant     10000      
  3     73       Leader         30000      
  3     78       Team Leader    8000       

Это SQL-запрос, который я использовал для group_concat для итогов и substring_index для разделения сгруппированных значений по каждому столбцу (P1, P2, P3).

SELECT *, GROUP_CONCAT(lid) as lids, GROUP_CONCAT(pyear) as pyears, 
 COUNT(DISTINCT lib_id) AS total_count,
 CASE WHEN COUNT(*)>=1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(if (total is null,0,total) ORDER BY lid ASC SEPARATOR ' '),' ',1),' ',-1) END AS P1, 
 CASE WHEN COUNT(*)>=2 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(if (total is null,0,total) ORDER BY lid ASC SEPARATOR ' '),' ',2),' ',-1) END AS P2, 
 CASE WHEN COUNT(*)>=3 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(if (total is null,0,total) ORDER BY lid ASC SEPARATOR ' '),' ',3),' ',-1) END AS P3
 FROM ( 
  SELECT * FROM view_items WHERE lid='1' 
  UNION 
  SELECT * FROM view_items WHERE lid='2' 
  UNION
  SELECT * FROM view_items WHERE lid='3' 
 ) AS AZ GROUP BY class_id

Это результат вышеуказанного запроса:

class id    class         lids     P1      P2      P3
---------   -----        -----    ----    ----     ----            
   73      Leader         1,2,3   10000   20000   30000  
   76      Staff          2       8000   
   77      Consultant     1,2     8000    10000   
   78      Team Leader    3       8000             
   83      Coordinator    1       6000                 

Крышки всегда должны иметь три счета, даже если запись не существует, следует добавить нулевое или нулевое значение. Как сделать добавление нулевого значения?

Это ожидаемый результат, который мне нужен.

 class id    class         lids     P1      P2      P3
---------   -----        -----    ----    ----     ----            
   73      Leader         1,2,3   10000   20000   30000  
   76      Staff          0,2,0     0     8000      0
   77      Consultant     1,2,0    8000   10000     0
   78      Team Leader    0,0,3     0       0      8000             
   83      Coordinator    1,0,0    6000     0       0            

В качестве альтернативы рассмотрите возможность обработки проблем с отображением в коде приложения, если это возможно.

Strawberry 29.05.2019 08:37

У вас есть таблица классов, в которой перечислены все классы?

mkRabbani 29.05.2019 08:40

Да, есть классная таблица.

codeseeker 29.05.2019 09:40
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
3
84
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Используйте else 0 в case expression

SELECT *, GROUP_CONCAT(lid) as lids, GROUP_CONCAT(pyear) as pyears, 
 COUNT(DISTINCT lib_id) AS total_count,
 CASE WHEN COUNT(*)>=1 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(if (total is null,0,total) ORDER BY lid ASC SEPARATOR ' '),' ',1),' ',-1) else 0 END AS P1, 
 CASE WHEN COUNT(*)>=2 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(if (total is null,0,total) ORDER BY lid ASC SEPARATOR ' '),' ',2),' ',-1) else 0 END AS P2, 
 CASE WHEN COUNT(*)>=3 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(if (total is null,0,total) ORDER BY lid ASC SEPARATOR ' '),' ',3),' ',-1) else 0 END AS P3
 FROM ( 
  SELECT * FROM view_items WHERE lid='1' 
  UNION 
  SELECT * FROM view_items WHERE lid='2' 
  UNION
  SELECT * FROM view_items WHERE lid='3' 
 ) AS AZ GROUP BY class_id
Ответ принят как подходящий

Чтобы получить 0 значений, где в таблице нет lid, вам нужно создать список всех значений lid для всех значений class_id, что вы можете сделать с CROSS JOIN из двух запросов SELECT DISTINCT (один для lid, один для class_id). Затем это можно LEFT JOINзанести в таблицу, чтобы получить требуемое total значение для каждой P группы с помощью условной агрегации:

SELECT c.class_id,
       MAX(v.class),
       GROUP_CONCAT(COALESCE(v.lid, 0) ORDER BY l.lid) AS lids,
       MAX(CASE WHEN v.lid=1 THEN total ELSE 0 END) AS P1,
       MAX(CASE WHEN v.lid=2 THEN total ELSE 0 END) AS P2,
       MAX(CASE WHEN v.lid=3 THEN total ELSE 0 END) AS P3
FROM (SELECT DISTINCT lid FROM view_items) l
CROSS JOIN (SELECT DISTINCT class_id FROM view_items) c
LEFT JOIN view_items v ON v.lid = l.lid AND v.class_id = c.class_id
GROUP BY c.class_id

Выход:

class_id    class       lids    P1      P2      P3
73          Leader      1,2,3   10000   20000   30000
76          Staff       0,2,0   0       8000    0
77          Consultant  1,2,0   8000    10000   0
78          Team Leader 0,0,3   0       0       8000
83          Coordinator 1,0,0   6000    0       0

Демо на dbfiddle

Потрясающий! спасибо за этот dbfiddle... Я просто немного настроил и сохранил UNION, это то, что мне нужно, чтобы получить правильные значения.

codeseeker 10.06.2019 07:31

Я думаю, проблема в том, что вы говорите, что count >= 1, но count >= 3 также является count >=1, поэтому ваш код никогда не достигает этой строки. Ты должен сказать, СЛУЧАЙ, КОГДА COUNT() >=1 И СЧИТАТЬ () < 2... СЛУЧАЙ, КОГДА COUNT() >=2 И СЧЕТ () < 3...

Я не думаю, что GROUP_CONCAT() это правильный подход к тому, что вы хотите. Попробуй это:

SELECT vi.class_id, vi.class,
       COUNT(DISTINCT vi.lib_id) AS total_count,
       CONCAT_WS(',',
                 MAX(CASE WHEN vi.lid = 1 THEN 1 ELSE 0 END),
                 MAX(CASE WHEN vi.lid = 2 THEN 1 ELSE 0 END),
                 MAX(CASE WHEN vi.lid = 3 THEN 1 ELSE 0 END)
                ) as lids,
       SUM(CASE WHEN vi.lid = 1 THEN vi.total ELSE 0 END) as total_1,
       SUM(CASE WHEN vi.lid = 2 THEN vi.total ELSE 0 END) as total_2,
       SUM(CASE WHEN vi.lid = 3 THEN vi.total ELSE 0 END) as total_3
FROM view_items vi
WHERE vi.lid IN (1, 2, 3) 
GROUP BY vi.class_id;

Примечания:

  • Ваш подзапрос и UNION не нужны. В MySQL они могут на самом деле иметь производительность причинить боль.
  • Я предполагаю, что lid — это число, поэтому я удалил одинарные кавычки.
  • Вы можете использовать условную агрегацию для каждой нужной суммы. Парсинг GROUP_CONCAT() не является правильным способом сделать это.
  • Ваш вопрос касается lids. CONCAT_WS() делает то, что вы хотите — объединяет либо значение (если оно появляется), либо ноль, если оно не появляется.

Другие вопросы по теме