Sqlite 排序依据,AaBbCc
Sqlite order by, AaBbCc
我一直在尝试让 sqlite 按以下顺序按名称对一组条目进行排序
AaBbCcDd......Zz
但我得到的最接近的结果是使用 COLLATE NOCASE 进行不区分大小写的排序。
我的条目是
Addy|2000-01-22T16:06:14.155Z
alice|2000-01-22T16:06:20.514Z
billyRay|2000-01-22T16:06:36.175Z
Bobby|2000-01-22T16:06:26.868Z
claus|2000-01-22T16:06:52.531Z
CoffinLLC|2000-01-22T15:33:11.235Z
Default|2000-01-22T15:55:12.168Z
我在 sqlite3 命令行中尝试了以下 select 语句来实现我的目标,但没有成功。
select * from t1 order by name COLLATE NOCASE asc;
select * from t1 order by name COLLATE NOCASE, name asc;
select * from t1 order by lower(name), name asc;
select * from t1 order by name, lower(name) asc;
根据@Griddoor 的初始评论,我尝试了一些变体,以下似乎有效
select * from t1 order by lower(substr(name,1,1)), name;
const CHAR_CODE_a = 'a'.charCodeAt(0); // 97
const CHAR_CODE_A = 'A'.charCodeAt(0); // 65
const CHAR_CODE_z = 'z'.charCodeAt(0); // 112
const CHAR_CODE_Z = 'Z'.charCodeAt(0); // 90
const diffLowerUpper = CHAR_CODE_a - CHAR_CODE_A;
const isLower = (charCode) => {
return CHAR_CODE_a <= charCode && charCode <= CHAR_CODE_z;
};
const isUpper = (charCode) => {
return CHAR_CODE_A <= charCode && charCode <= CHAR_CODE_Z;
};
const ORDER = {
KEEP : 1,
EXCHANGE : -1,
EQUAL : 0,
}
const A1Bigger = (isAsc) => {
// 以降序的角度考虑,A1大,那么保持即可
return isAsc ? ORDER.EXCHANGE : ORDER.KEEP;
};
const A2Bigger = (isAsc) => {
// 以降序的角度考虑,A2大,那么需要跟A1交换位置
return isAsc ? ORDER.KEEP : ORDER.EXCHANGE;
};
/**
* 比较 A2 字符串与 A1 字符串在第index位谁更大
* 这里的排序规则为: a < A < b < B < c < C 与OfficeExcel保持一致
* @param A2
* @param A1
* @param isAsc
* @param index
*/
const excelStringCompare = (A2, A1, isAsc, index = 0) => {
if(A2 === A1) {
return ORDER.EQUAL
}
const charCodeA1 = A1.charCodeAt(index), charCodeA2 = A2.charCodeAt(index)
// 两个字串相等情况以及处理,会有NaN一定是有一个长度大于另一个,而charCodeAt(index)等于NaN的就说明他的长度更短
if(isNaN(charCodeA1)) {
return A2Bigger(isAsc);
} else if(isNaN(charCodeA2)) {
return A1Bigger(isAsc);
}
// 都是小写或都是大写
if ((isLower(charCodeA1) && isLower(charCodeA2)) || (isUpper(charCodeA1) && isUpper(charCodeA2))) {
if (charCodeA2 < charCodeA1) {
return A1Bigger(isAsc);
}
if (charCodeA2 > charCodeA1) {
return A2Bigger(isAsc);
}
// 当两个字符串这个位相等的时候再比较下个位
return excelStringCompare(A2, A1, isAsc, index + 1 )
}
// A1 小写 A2 大写
else if (isLower(charCodeA1) && isUpper(charCodeA2)) {
// a - A
if (charCodeA1 - charCodeA2 === diffLowerUpper) {
return A1Bigger(isAsc);
} else {
// c - (a - A) < D 即 (c - a = 2) < (D - A = 3)
if (charCodeA1 - diffLowerUpper < charCodeA2) {
return A2Bigger(isAsc);
} else {
return A1Bigger(isAsc);
}
}
}
// A1 大写 A2 小写
else {
// A - a === - (a - A)
if (charCodeA1 - charCodeA2 === -diffLowerUpper) {
return A2Bigger(isAsc);
} else {
// C + (a - A) < d 即 (C - A = 2) < (d - a = 3)
if (charCodeA1 + diffLowerUpper < charCodeA2) {
return A2Bigger(isAsc);
} else {
return A1Bigger(isAsc);
}
}
}
};
const isAsc = true;// 升降序
let strArr = ['a','Ab', 'b', 'aB', 'A', 'B', 'ab', 'AB', 'c', 'D', 'd', 'C']
strArr.sort((a, b) => {
return excelStringCompare(a, b, isAsc)
})
console.log(strArr)
我一直在尝试让 sqlite 按以下顺序按名称对一组条目进行排序
AaBbCcDd......Zz
但我得到的最接近的结果是使用 COLLATE NOCASE 进行不区分大小写的排序。
我的条目是
Addy|2000-01-22T16:06:14.155Z
alice|2000-01-22T16:06:20.514Z
billyRay|2000-01-22T16:06:36.175Z
Bobby|2000-01-22T16:06:26.868Z
claus|2000-01-22T16:06:52.531Z
CoffinLLC|2000-01-22T15:33:11.235Z
Default|2000-01-22T15:55:12.168Z
我在 sqlite3 命令行中尝试了以下 select 语句来实现我的目标,但没有成功。
select * from t1 order by name COLLATE NOCASE asc;
select * from t1 order by name COLLATE NOCASE, name asc;
select * from t1 order by lower(name), name asc;
select * from t1 order by name, lower(name) asc;
根据@Griddoor 的初始评论,我尝试了一些变体,以下似乎有效
select * from t1 order by lower(substr(name,1,1)), name;
const CHAR_CODE_a = 'a'.charCodeAt(0); // 97
const CHAR_CODE_A = 'A'.charCodeAt(0); // 65
const CHAR_CODE_z = 'z'.charCodeAt(0); // 112
const CHAR_CODE_Z = 'Z'.charCodeAt(0); // 90
const diffLowerUpper = CHAR_CODE_a - CHAR_CODE_A;
const isLower = (charCode) => {
return CHAR_CODE_a <= charCode && charCode <= CHAR_CODE_z;
};
const isUpper = (charCode) => {
return CHAR_CODE_A <= charCode && charCode <= CHAR_CODE_Z;
};
const ORDER = {
KEEP : 1,
EXCHANGE : -1,
EQUAL : 0,
}
const A1Bigger = (isAsc) => {
// 以降序的角度考虑,A1大,那么保持即可
return isAsc ? ORDER.EXCHANGE : ORDER.KEEP;
};
const A2Bigger = (isAsc) => {
// 以降序的角度考虑,A2大,那么需要跟A1交换位置
return isAsc ? ORDER.KEEP : ORDER.EXCHANGE;
};
/**
* 比较 A2 字符串与 A1 字符串在第index位谁更大
* 这里的排序规则为: a < A < b < B < c < C 与OfficeExcel保持一致
* @param A2
* @param A1
* @param isAsc
* @param index
*/
const excelStringCompare = (A2, A1, isAsc, index = 0) => {
if(A2 === A1) {
return ORDER.EQUAL
}
const charCodeA1 = A1.charCodeAt(index), charCodeA2 = A2.charCodeAt(index)
// 两个字串相等情况以及处理,会有NaN一定是有一个长度大于另一个,而charCodeAt(index)等于NaN的就说明他的长度更短
if(isNaN(charCodeA1)) {
return A2Bigger(isAsc);
} else if(isNaN(charCodeA2)) {
return A1Bigger(isAsc);
}
// 都是小写或都是大写
if ((isLower(charCodeA1) && isLower(charCodeA2)) || (isUpper(charCodeA1) && isUpper(charCodeA2))) {
if (charCodeA2 < charCodeA1) {
return A1Bigger(isAsc);
}
if (charCodeA2 > charCodeA1) {
return A2Bigger(isAsc);
}
// 当两个字符串这个位相等的时候再比较下个位
return excelStringCompare(A2, A1, isAsc, index + 1 )
}
// A1 小写 A2 大写
else if (isLower(charCodeA1) && isUpper(charCodeA2)) {
// a - A
if (charCodeA1 - charCodeA2 === diffLowerUpper) {
return A1Bigger(isAsc);
} else {
// c - (a - A) < D 即 (c - a = 2) < (D - A = 3)
if (charCodeA1 - diffLowerUpper < charCodeA2) {
return A2Bigger(isAsc);
} else {
return A1Bigger(isAsc);
}
}
}
// A1 大写 A2 小写
else {
// A - a === - (a - A)
if (charCodeA1 - charCodeA2 === -diffLowerUpper) {
return A2Bigger(isAsc);
} else {
// C + (a - A) < d 即 (C - A = 2) < (d - a = 3)
if (charCodeA1 + diffLowerUpper < charCodeA2) {
return A2Bigger(isAsc);
} else {
return A1Bigger(isAsc);
}
}
}
};
const isAsc = true;// 升降序
let strArr = ['a','Ab', 'b', 'aB', 'A', 'B', 'ab', 'AB', 'c', 'D', 'd', 'C']
strArr.sort((a, b) => {
return excelStringCompare(a, b, isAsc)
})
console.log(strArr)