[英]Some sort of loop to move NULL values to last column in a number of columns?
I'm returning 4 columns in my query, each of which can contain information or be a NULL value.我在查询中返回 4 列,每列都可以包含信息或为 NULL 值。 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?
有没有办法创建某种循环,以便对于每一行,所有非 NULL 值都移动到最左边的列,最后有 NULL? 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.尽管有一些有趣的评论,但这可能在大多数 RDMS 中都可以做到,只要它们支持数组函数。 (There will be variation in how it's done).
(它的完成方式会有所不同)。 I made the example table more complicated to show more possible cases.
我使示例表更复杂,以显示更多可能的情况。
Schema (PostgreSQL v13)架构 (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 ![]() |
View on DB Fiddle在 DB Fiddle 上查看
Schema (MySQL v8.0)架构 (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 ![]() |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.