【问题标题】:MySQL - match post code based on one or two first charactersMySQL - 基于一个或两个第一个字符匹配邮政编码
【发布时间】:2012-01-26 17:29:15
【问题描述】:

我正在尝试创建一个 SQL 语句,以根据提供的邮政编码和数据库中存储的邮政编码加上重量方面来查找匹配记录。

数据库中的邮政编码介于 1 或 2 个字符之间,即 B、BA ...

现在 - 传递给 SQL 语句的值将始终包含客户邮政编码的前 2 个字符。我怎样才能找到它的匹配项?假设我有一个邮政编码 B1,它只会匹配数据库中的单个 B 加上重量方面,我可以接受。

这是我当前的SQL语句,它也考虑了超过一定重量的免费送货的因素:

SELECT `s`.*,
IF (
    '{$weight}' > (
        SELECT MAX(`weight_from`)
        FROM `shipping`
        WHERE UPPER(SUBSTRING(`post_code`, 1, 2)) = 'B1'
    ),
    (
        SELECT `cost`
        FROM `shipping`
        WHERE UPPER(SUBSTRING(`post_code`, 1, 2)) = 'B1'
        ORDER BY `weight_from` DESC
        LIMIT 0, 1
    ),
    `s`.`cost`
) AS `cost`
FROM `shipping` `s`
WHERE UPPER(SUBSTRING(`s`.`post_code`, 1, 2)) = 'B1'
AND 
(
    (
        '{$weight}' > (
            SELECT MAX(`weight_from`)
            FROM `shipping`
            WHERE UPPER(SUBSTRING(`post_code`, 1, 2)) = 'B1'
        )
    )
    OR 
    ('{$weight}' BETWEEN `s`.`weight_from` AND `s`.`weight_to`)
)
LIMIT 0, 1

然而,上面使用了 SUBSTRING() 函数,其中硬编码的字符数设置为 2 - 这是我真正需要一些帮助以使其仅匹配与提供的邮政编码匹配的字符数 - 在本例中为 B1。

Marcus - 感谢您的帮助 - 出色的示例 - 对于那些也想知道的人来说,这就是我的代码的样子:

首先,我运行以下语句来获取正确的邮政编码:

(
    SELECT `post_code`
    FROM `shipping`
    WHERE `post_code` = 'B1'
)
UNION
(
    SELECT `post_code`
    FROM `shipping`
    WHERE `post_code` = SUBSTRING('B1', 1, 1)
)
ORDER BY `post_code` DESC
LIMIT 0, 1

然后,根据分配给“post_code”索引的返回值,我的第二条语句后跟:

$post_code = $result['post_code'];

SELECT `s`.*,
IF (
    '1000' > (
        SELECT MAX(`weight_from`)
        FROM `shipping`
        WHERE `post_code` = '{$post_code}'  
    ),
    (
        SELECT `cost`
        FROM `shipping`
        WHERE `post_code` = '{$post_code}'
        ORDER BY `weight_from` DESC
        LIMIT 0, 1
    ),
    `s`.`cost`
) AS `cost`
FROM `shipping` `s`
WHERE `s`.`post_code` = '{$post_code}'
AND 
(
    (
        '1000' > (
            SELECT MAX(`weight_from`)
            FROM `shipping`
            WHERE `post_code` = '{$post_code}'
            ORDER BY LENGTH(`post_code`) DESC
        )
    )
    OR 
    ('1000' BETWEEN `s`.`weight_from` AND `s`.`weight_to`)
)
LIMIT 0, 1

【问题讨论】:

    标签: mysql postal-code


    【解决方案1】:

    以下查询将获得所有结果,其中运输表中的 post_code 与传入的 post_code 的开头匹配,然后将其从最显式到最显式排序,返回最显式的结果:

    SELECT *
    FROM shipping
    WHERE post_code = SUBSTRING('B1', 1, LENGTH(post_code))
    ORDER BY LENGTH(post_code) DESC
    LIMIT 1
    

    更新

    虽然这个查询很灵活,但速度不是很快,因为它不能利用索引。如果运输表很大,并且您最多只能传递两个字符,那么进行两个单独的调用可能会更快。

    首先,尝试最明确的调用。

    SELECT *
    FROM shipping
    WHERE post_code = 'B1'
    

    如果没有返回结果,则搜索单个字符:

    SELECT *
    FROM shipping
    WHERE post_code = SUBSTRING('B1', 1, 1)
    

    当然,如果您必须在一次调用中完成,您可以将这些与 UNION 结合起来:

    SELECT * FROM
    ((SELECT *
    FROM shipping
    WHERE post_code = 'B1')
    UNION
    (SELECT *
    FROM shipping
    WHERE post_code = SUBSTRING('B1', 1, 1))) a
    ORDER BY post_code DESC
    LIMIT 1
    

    【讨论】:

    • 谢谢马库斯 - 我会马上试一试,看看效果如何。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多