【问题标题】:Sort Postcode for menu/list为菜单/列表排序邮政编码
【发布时间】:2009-04-27 09:11:21
【问题描述】:

我需要按顺序对英国邮政编码列表进行排序。

有简单的方法吗?

英国邮政编码由字母和数字组成:

有关格式的完整信息,请参阅: http://en.wikipedia.org/wiki/UK_postcodes

但我的问题是这种简单的 alpha 排序不起作用,因为每个代码都以 1 或两个字母开头,然后紧跟一个数字,最多两位数字,然后是空格,另一个数字,然后是一个字母。例如LS1 1AA 或 ls28 1AA,还有另一种情况,一旦第一部分的数字超过 99 就继续 9A 等等。

Alpha 排序导致 10 紧跟在 1 之后:

...
LS1 9ZZ
LS10 1AA
...
LS2 

我正在考虑创建一个 SQL 函数来将可打印的邮政编码转换为可排序的邮政编码,例如'LS1 9ZZ' 会变成 'LS01 9ZZ',然后在 order by 子句中使用这个函数。

有没有人做过这个或类似的事情?

【问题讨论】:

  • 我认为(可能)用户从中选择的菜单或邮政编码列表是一个相当不愉快的 UI,除非列表可以保持非常短。如果你真的需要这样做,alpha 排序可能和任何东西一样好——我的工作邮政编码不符合你的模式——它是 ec1a 2ay。你想把它放在排序列表的哪个位置?
  • 同意 - 我将更改 UI 方法。

标签: sql sorting postal-code


【解决方案1】:

您需要将此视为标记化问题,因此 SW1A 1AA 应标记化为:

  • 软件
  • 1
  • 一个
  • 1AA

(尽管如果你愿意,你可以把向内的部分分解成 1 和 AA)

并且 G12 8QT 应该标记为:

  • G
  • 12
  • (空字符串)
  • 8QT

一旦您将邮政编码分解为这些组成部分,那么排序应该很容易。 GIR 0AA 邮政编码有一个例外,但您可以硬编码该邮政编码的测试

编辑:关于标记化的更多想法

对于示例邮政编码 SW1A 1AA,SW 是邮政编码区,1A 是邮政编码区(我们将其分成两部分进行排序),1 是邮政编码扇区,AA 是单位邮政编码。

这些是有效的邮政编码格式(来源:Royal Mail PAF 用户指南第 8 页 - this page 底部的链接):

NAA
AAN NAA
安纳
全日空航空
AAA NAA(仅适用于 GIR 0AA 代码)
安安NAA
AANA NAA

所以一个粗略的算法将是(假设我们想要分离部门和单位邮政编码):

  • 代码 = GIR 0AA?标记为 GI/R/ /0/AA(将 R 视为区简化事情)
  • 代码 5 个字母长,例如 G1 3AF?标记为 G/1/ /3/AF
  • 编码 6 个字母长,第三个字符为字母,例如W1P 1HQ?代币化到 W/1/P/1/HQ
  • 编码 6 个字母长,第二个字符为字母,例如CR2 6XH?标记为 CR/2/ /6/XH
  • 编码 7 个字母长,第 4 个字符为字母,例如EC1A 1BB?标记为 EC/1/A/1/BB
  • 否则,例如TW14 2ZZ,tokenize 到 TW/14/ /2/ZZ

如果目的是显示邮政编码列表供用户选择,那么我会采用 Neil Butterworth 的建议,即在数据库中存储邮政编码的“可排序”版本。创建可排序版本的最简单方法是将所有条目填充为九个字符:

  • 区域的两个字符(如果更短,则为右填充)
  • 两个代表区号(如果更短,则在左侧填充)
  • 一个用于地区字母(如果缺少则填写)
  • 空间
  • 一个用于行业
  • 两个为单位

GIR 0AA 又是一个小例外。如果你用空格填充,那么排序顺序应该是正确的。使用 # 表示空格的示例:

  • W1#1AA => W##1##1AA
  • WC1#1AA => WC#1##1AA
  • W10#1AA => W#10##1AA
  • W1W#1AA => W##1W#1AA
  • GIR#0AA => GI#R##0AA
  • WC10#1AA => WC10##1AA
  • WC1W#1AA => WC#1W#1AA

如果区域太短,您需要右填充:左填充会产生错误的排序顺序。所有单字母区域 - B、E、G、L、M、N、S、W - 将排在所有两个字母区域 - AB、AL、...、ZE 之前 - 如果您左填充

区号需要留补,保证W1、W2、...、W9、W10的自然顺序保持不变

【讨论】:

  • 虽然“标记化”并不简单,因为没有通常的分隔符......
  • 我添加了一个粗略的分词算法和一些关于如何存储结果的想法
  • 谢谢 - 我不能再标记你回答了,希望其他人会。
【解决方案2】:

我知道这已经晚了几年,但我也刚刚遇到过这个问题。 我已经设法用以下代码克服了它,所以我想我会在搜索互联网时分享,但找不到任何东西!

mysql_query("SELECT SUBSTRING_INDEX(postcode,' ',1) as p1, SUBSTRING_INDEX(postcode,' ',-1) as p2 from `table` ORDER BY LENGTH(p1), p1, p2 ASC");

此代码将采用完整的英国邮政编码并将其拆分为 2。

然后它将按邮政编码的第一部分排序,然后是第二部分。

【讨论】:

    【解决方案3】:

    我很想将规范化的邮政编码与真实的邮政编码一起存储在数据库中 - 这样您只需执行一次字符串操作,并且可以使用索引来帮助您进行排序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      相关资源
      最近更新 更多