У меня есть этот 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
У вас есть таблица классов, в которой перечислены все классы?
Да, есть классная таблица.
Используйте 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... Я просто немного настроил и сохранил UNION, это то, что мне нужно, чтобы получить правильные значения.
Я думаю, проблема в том, что вы говорите, что 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()
не является правильным способом сделать это.lid
s. CONCAT_WS()
делает то, что вы хотите — объединяет либо значение (если оно появляется), либо ноль, если оно не появляется.
В качестве альтернативы рассмотрите возможность обработки проблем с отображением в коде приложения, если это возможно.