如何通过邮政编码订购?

时间:2018-02-28 16:21:26

标签: sql reporting-services sql-order-by

我有一份小报告需要通过邮政编码排序。我该怎么做?

使用ORDER BY Postcode返回

SK1
SK11
SK13
SK2

如何返回

SK1
SK2
SK11
SK13

修改

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

5 个答案:

答案 0 :(得分:1)

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

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

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

order by postcode_num

根据需要的结果:

enter image description here

答案 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

备注

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

答案 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>