I'm returning 4 columns in my query, each of which can contain information or be a NULL value. Is there a way to create some sort of loop so that for each row, all the non-NULL values are moved the left most columns with the NULLs at the end? Or perhaps with the use of functions?
My situation:
Value 1 | Value 2 | Value 3 | Value 4 |
---|---|---|---|
5 | 3 | NULL | 1 |
6 | NULL | NULL | 3 |
My desired result:
Value 1 | Value 2 | Value 3 | Value 4 |
---|---|---|---|
5 | 3 | 1 | NULL |
6 | 3 | NULL | NULL |
Despite the interesting comments, this can be done, probably in most RDMS as long as they support array functions. (There will be variation in how it's done). I made the example table more complicated to show more possible cases.
Schema (PostgreSQL v13)
CREATE TABLE t (
"value_1" INTEGER,
"value_2" INTEGER,
"value_3" INTEGER,
"value_4" INTEGER
);
INSERT INTO t
("value_1", "value_2", "value_3", "value_4")
VALUES
('5', '3', null, '1'),
('6', null, null, '3'),
('3', '2', '1', '0'),
(null, '2', null, '4'),
(null, null, '3', '4'),
(null, '3', '4', '5'),
(null, null, null, '4');
Query
SELECT all_vals[1] Value_1
, all_vals[2] Value_2
, all_vals[3] Value_3
, all_vals[4] Value_4
FROM (
SELECT array_remove(ARRAY[value_1, value_2, value_3, value_4], NULL) all_vals
FROM t
) arrs;
value_1 | value_2 | value_3 | value_4 |
---|---|---|---|
5 | 3 | 1 | |
6 | 3 | ||
3 | 2 | 1 | 0 |
2 | 4 | ||
3 | 4 | ||
3 | 4 | 5 | |
4 |
Schema (MySQL v8.0)
CREATE TABLE t (
`value_1` INTEGER,
`value_2` INTEGER,
`value_3` INTEGER,
`value_4` INTEGER
);
INSERT INTO t
(`value_1`, `value_2`, `value_3`, `value_4`)
VALUES
('5', '3', null, '1'),
('6', null, null, '3'),
('3', '2', '1', '0'),
(null, '2', null, '4'),
(null, null, '3', '4'),
(null, '3', '4', '5'),
(null, null, null, '4');
Query
SELECT all_values -> "$[0]" value_1
, all_values -> "$[1]" value_2
, all_values -> "$[2]" value_3
, all_values -> "$[3]" value_4
FROM ( -- The Ordering here matters, as they appear to change the index when removed, so I had to work back to front.
-- $[4] (Or any value outside the range) is necessary, as a NULL will cause the whole thing to return NULL.
SELECT JSON_REMOVE(JSON_ARRAY(value_1, value_2, value_3, value_4)
, CASE WHEN value_4 IS NULL THEN "$[3]" ELSE "$[4]" END
, CASE WHEN value_3 IS NULL THEN "$[2]" ELSE "$[4]" END
, CASE WHEN value_2 IS NULL THEN "$[1]" ELSE "$[4]" END
, CASE WHEN value_1 IS NULL THEN "$[0]" ELSE "$[4]" END
) all_values
FROM t) arr;
value_1 | value_2 | value_3 | value_4 |
---|---|---|---|
5 | 3 | 1 | |
6 | 3 | ||
3 | 2 | 1 | 0 |
2 | 4 | ||
3 | 4 | ||
3 | 4 | 5 | |
4 |
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.