英文:
Sort mysql result by two column, but with a “holed” column
问题
我有以下的初始情况:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
| 0 | NULL |
| 1 | 6 |
| 2 | NULL |
| 3 | 1 |
| 4 | NULL |
| 5 | NULL |
| 6 | 2 |
+------------+-------------+
你可以通过以下模式生成这个表格:
CREATE TABLE two_column_order (
legacyRank VARCHAR(45),
forcedRank VARCHAR(45)
);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (5, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (6, 2);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (7, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (0, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (1, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (2, 6);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (3, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (4, 1);
SELECT * FROM two_column_order
order by
CASE when `forcedRank` <> NULL THEN `forcedRank`
ELSE `legacyRank`
END
目标是将每一行中没有NULL的forcedRank
列放在forcedRank
列中指定的准确位置。期望的结果如下:
+------------+-------------+
| legacyRank | forcedRank |
0 | 0 | NULL |
1 | 3 | 1 |
2 | 6 | 2 |
3 | 2 | NULL |
4 | 4 | NULL |
5 | 5 | NULL |
6 | 6 | 6 |
+------------+-------------+
如你所见,如果forcedRank
列不是NULL,每一行都按照forcedRank
列的顺序排列。当NULL行仍然按照legacyRank
列在非NULL行未占用的位置上排序,但不会移动强制行。
在这个顺序中,我尝试在ORDER BY
中使用CASE WHEN
语法,如下:
SELECT * FROM two_column_order
order by
CASE WHEN (`forcedRank` is NULL ) THEN `legacyRank`
END ,
-`forcedRank` DESC,
`legacyRank`
但结果并不符合我的期望:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
| 3 | 1 |
| 6 | 2 |
| 6 | 6 |
| 0 | NULL |
| 2 | NULL |
| 4 | NULL |
| 5 | NULL |
+------------+-------------+
那么,如何使legacyRank
列在不移动强制行的情况下获得顺序?
英文:
I have the following initial situation:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
| 0 | NULL |
| 1 | 6 |
| 2 | NULL |
| 3 | 1 |
| 4 | NULL |
| 5 | NULL |
| 6 | 2 |
+------------+-------------+
You could generate this table by the following schema:
CREATE TABLE two_column_order (
legacyRank VARCHAR(45),
forcedRank VARCHAR(45)
);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (5, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (6, 2);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (7, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (0, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (1, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (2, 6);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (3, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (4, 1);
SELECT * FROM two_column_order
order by
CASE when `forcedRank` <> NULL THEN `forcedRank`
ELSE `legacyRank`
END
The goal is to put each line with no-NULL forcedRank
column in the accurate position mentioned in this forcedRank
column. The expected rendering is like:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
0 | 0 | NULL |
1 | 3 | 1 |
2 | 6 | 2 |
3 | 2 | NULL |
4 | 4 | NULL |
5 | 5 | NULL |
6 | 6 | 6 |
+------------+-------------+
As you see, each line take the position ordered by the forcedRank
column if not NULL. When the the NULL rows still sorted by the legacyRank
column in the positions leaved unoccupied by the non-NULL rows, but never shift the forced rows.
In this order, I tried to use the CASE WHEN
syntax inside the ORDER BY
like this:
SELECT * FROM two_column_order
order by
CASE WHEN (`forcedRank` is NULL ) THEN `legacyRank`
END ,
-`forcedRank` DESC,
`legacyRank`
But the result doesn’t really feat my expectations:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
| 3 | 1 |
| 6 | 2 |
| 6 | 6 |
| 0 | NULL |
| 2 | NULL |
| 4 | NULL |
| 5 | NULL |
+------------+-------------+
So how can I make the legacyRank
column get order beyond the forcedrank rows without shift them?
答案1
得分: 1
NULL
不能像这样进行比较,您需要使用 IS
或在您的情况下使用 IS NOT
。
SELECT * FROM two_column_order
order by
CASE when `forcedRank` IS NOT NULL THEN `forcedRank`
ELSE `legacyRank`
END
legacyRank | forcedRank |
---|---|
0 | null |
1 | null |
4 | 1 |
6 | 2 |
3 | null |
5 | null |
2 | 6 |
7 | null |
由于第一个答案不会给出正确的答案。
我通过在原始数字中添加一个小数点来更改排序,使其大于新的强制排名。这将保持顺序,如果强制编号小于传统排名,它将为您提供以下结果。
SELECT * FROM two_column_order
order by
CASE when `forcedRank` IS NOT NULL THEN `forcedRank`
ELSE `legacyRank` + .1
END
legacyRank | forcedRank |
---|---|
0 | null |
4 | 1 |
1 | null |
6 | 2 |
3 | null |
5 | null |
2 | 6 |
7 | null |
英文:
NULL
can't tbe comapred like that you need to use IS
or in your case IS NOT
SELECT * FROM two_column_order
order by
CASE when `forcedRank` IS NOT NULL THEN `forcedRank`
ELSE `legacyRank`
END
legacyRank | forcedRank |
---|---|
0 | null |
1 | null |
4 | 1 |
6 | 2 |
3 | null |
5 | null |
2 | 6 |
7 | null |
As the first answer won't give you the correct answer.
i have changed the order by adding a decimal point to the original number so that it will be bigger than the new forced rank.
it will keep the order and a the forced number is smaller then the legayrank, it get you follwoing result
SELECT * FROM two_column_order
order by
CASE when `forcedRank` IS NOT NULL THEN `forcedRank`
ELSE `legacyRank` + .1
END
legacyRank | forcedRank |
---|---|
0 | null |
4 | 1 |
1 | null |
6 | 2 |
3 | null |
5 | null |
2 | 6 |
7 | null |
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论