MySQL - съответства на пощенския код въз основа на един или два първи знака

Опитвам се да създам 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.

Маркъс - благодаря за помощта - изключителен пример - ето как изглежда моят код за тези, които също се чудят:

Първо изпълних следния оператор, за да получа правилния пощенски код:

(
    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

person user398341    schedule 26.01.2012    source източник


Отговори (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
person Marcus Adams    schedule 26.01.2012
comment
Благодаря, Маркъс - ще го пробвам след секунда и ще видя как ще стане. - person user398341; 26.01.2012