CREATE TEMPORARY TABLE temp1 (id int, reg1 int default 0, reg2 int default 0, reg3 int default 0, reg4 int default 0);
/* Заполнение */
INSERT INTO temp1 (id) VALUES ('1');
INSERT INTO temp1 (id) VALUES ('2');
INSERT INTO temp1 (id) VALUES ('3');
INSERT INTO temp1 (id) VALUES ('4');
INSERT INTO temp1 (id) VALUES ('5');
INSERT INTO temp1 (id) VALUES ('6');
INSERT INTO temp1 (id) VALUES ('7');
INSERT INTO temp1 (id) VALUES ('8');
INSERT INTO temp1 (id) VALUES ('9');
SELECT t.id, coalesce(subquery.reg1, t.reg1), coalesce(subquery.reg2, t.reg2), coalesce(subquery.reg3, t.reg3), coalesce(subquery.reg4, t.reg4)
FROM temp1 t
LEFT JOIN
(
select category, sum(number*(1-abs(sign(region-1)))) as reg1,
sum(number*(1-abs(sign(region-2)))) as reg2,
sum(number*(1-abs(sign(region-3)))) as reg3,
sum(number*(1-abs(sign(region-4)))) as reg4
from groups JOIN orders USING (id_order)
WHERE datetime_order >= '$date_start' AND datetime_order <= '$date_end'
group by category
) subquery ON t.id = subquery.category;
DROP TABLE temp1;
Делается через временную таблицу