我有一份小报告需要通过邮政编码排序。我该怎么做?
使用ORDER BY Postcode
返回
SK1
SK11
SK13
SK2
如何返回
SK1
SK2
SK11
SK13
修改
我应该在这个问题上添加更多内容,我正在使用整个英国的邮政编码,而不仅仅是以SK开头的邮政编码。所以这些邮政编码中的一些只会以1个字母开头,有些则以2开头。此外,邮政编码的第二部分也在列中。
答案 0 :(得分:1)
假设MSSQL,并且您的邮政编码字段遵循一致的Char(2)+ Number模式,那么您可以添加计算查询列:
postcode_num = convert(int,substring(postcode,3,len(postcode)))
然后使用它代替Postcode进行排序:
order by postcode_num
根据需要的结果:
答案 1 :(得分:0)
创建2列:
1.第一部分的VARCHAR;
2.最后(数字)部分的TINYINT。
ORDER BY postcode_prefix, postcode_suffix
来源:https://www.sitepoint.com/community/t/order-by-postcode/50042/9
答案 2 :(得分:0)
您遇到的问题是您尝试ORDER BY的列是text类型而不是数字,因此SQL将执行您正在查看的排序。相反,如果您希望SQL对它进行排序,就好像它是一个数字,那么您需要将" SK"列的一部分,将数字字符转换为数字类型,然后按顺序排序。
这是@LONG在第一条评论中回复的内容。
答案 3 :(得分:0)
我接近它的方法是创建一些通用函数,在排序之前从字符串中去除alpha或数字部分。
在我的示例中,函数位于fn
架构中,因此请根据需要进行更改。
ORDER BY fn.StripToAlpha(PostCode), fn.StripToNumeric(PostCode)
这些类型的函数有很多例子,可能比我写的更有效但下面是生成我使用的函数的代码。
CREATE FUNCTION [fn].[StripToAlpha]
(
@inputString nvarchar(4000)
)
RETURNS varchar(4000)
AS
BEGIN
DECLARE @Counter as int
DECLARE @strReturnVal varchar(4000)
DECLARE @Len as int
DECLARE @ASCII as int
SET @Counter=0
SET @Len=LEN(@inputString)
SET @strReturnVal = ''
WHILE @Counter<=@Len
BEGIN
SET @Counter = @Counter +1
SET @ascii= ASCII(SUBSTRING(@inputString,@counter,1))
IF(@ascii BETWEEN 65 AND 90) OR (@ascii BETWEEN 97 AND 122)
BEGIN
SET @strReturnVal = @strReturnVal + (SUBSTRING(@inputString,@counter,1))
END
END
RETURN @strReturnVal
END
和
CREATE FUNCTION [fn].[StripToNumeric]
(
@inputString nvarchar(4000)
)
RETURNS Float
AS
BEGIN
DECLARE @Counter as int
DECLARE @strReturnVal varchar(4000)
DECLARE @ReturnVal Float
DECLARE @Len as int
DECLARE @ASCII as int
SET @Counter=0
SET @Len=LEN(@inputString)
SET @strReturnVal = ''
IF @inputString IS NULL
BEGIN
Return NULL
END
-- swap out comma for decimal
SET @inputString = REPLACE(@inputString, ',', '.')
IF @Len = 0 OR LEN(LTRIM(RTRIM(@inputString))) = 0
BEGIN
SET @ReturnVal=0
END
ELSE
BEGIN
WHILE @Counter<=@Len
BEGIN
SET @Counter = @Counter +1
SET @ascii= ASCII(SUBSTRING(@inputString,@counter,1))
IF(@ascii BETWEEN 48 AND 57) OR (@ascii IN (46,37))
BEGIN
SET @strReturnVal = @strReturnVal + (SUBSTRING(@inputString,@counter,1))
END
END
if RIGHT(@strReturnVal,1)='%'
BEGIN
SET @strReturnVal = LEFT(@strReturnVal,len(@strReturnVal)-1)
SET @strReturnVal = CAST((CAST(@strReturnVal AS FLOAT)/100) AS nvarchar(4000))
END
SET @ReturnVal = ISNULL(@strReturnVal,0)
END
RETURN @ReturnVal
END
备注
答案 4 :(得分:0)
您没有指定您使用的数据库;这是一个Oracle示例。希望你能够将它“转换”成其他东西。
这个想法是:使用正则表达式(在这种情况下似乎非常方便),将邮政编码分为两部分:字母和数字。当REGEXP_SUBSTR
返回一个字符串时,我将TO_NUMBER
函数应用于邮政编码的“数字”部分,以便对其进行正确排序。
SQL> with test (postcode) as
2 (select 'sk1' from dual union
3 select 'sk11' from dual union
4 select 'sk13' from dual union
5 select 'sk2' from dual
6 )
7 select postcode
8 from test
9 order by regexp_substr(postcode, '^[[:alpha:]]+'), --> letters
10 to_number(regexp_substr(postcode, '[[:digit:]]+$')); --> numbers
POST
----
sk1
sk2
sk11
sk13
SQL>