如何通过邮政编码订购?

问题描述 投票:0回答:5

我有一份小报告,需要通过邮政编码订购。我该怎么做呢?

使用ORDER BY Postcode返回

SK1
SK11
SK13
SK2

我怎么能回来

SK1
SK2
SK11
SK13

编辑

我应该在这个问题上添加更多内容,我正在使用整个英国的邮政编码,而不仅仅是以SK开头的邮政编码。因此,这些邮政编码中的一些将仅以1个字母开头,一些以2开头。此外,邮政编码的第二部分在列中。

sql reporting-services sql-order-by
5个回答
1
投票

假设MSSQL,并且您的Postcode字段遵循Char(2)+ Number的一致模式,那么您可以添加计算查询列:

postcode_num = convert(int,substring(postcode,3,len(postcode)))

然后用它代替Postcode进行排序:

order by postcode_num

结果如你所愿:

enter image description here


0
投票

创建2列: 1.第一部分的VARCHAR; 2.最后(数字)部分的TINYINT。

ORDER BY postcode_prefix, postcode_suffix

资料来源:https://www.sitepoint.com/community/t/order-by-postcode/50042/9


0
投票

您遇到的问题是您尝试ORDER BY的列是text类型而不是数字,因此SQL将执行您所看到的排序。相反,如果您希望SQL对它进行排序,就好像它是一个数字那么您需要对该列的“SK”部分进行子串,将数字字符转换为数字类型,然后按顺序排序。

这就是@LONG在第一条评论中回复的内容。


0
投票

我接近它的方法是创建一些通用函数,在排序之前将从字符串中删除字母或数字部分。

在我的示例中,函数位于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

笔记

  • 这不会影响您当前的使用,但StripToNumeric检查是一个百分号,并转换为小数,因此您将它传递25%,它将返回0.25。
  • 如果您使用完整的邮政编码(例如SK1 1AB),则它将无效,因为它将按SKAB排序,然后按11排序
  • 它将适用于具有较短前缀的邮政编码,例如M34(如果我没记错的那就是Denton!:))

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>
© www.soinside.com 2019 - 2024. All rights reserved.