Domanda

Sto cercando di creare un'istruzione SQL per trovare il record di corrispondenza in base al codice postale fornito e ai codici postali memorizzati nel database più l'aspetto del peso.

I codici postali nel database sono compresi tra 1 o 2 caratteri I.e. B, BA ...

Ora - Il valore passato all'istruzione SQL avrà sempre 2 primi caratteri del codice postale del client. Come posso trovare la partita per questo? Dì che ho un codice post B1, che corrisponderebbe solo al singolo B nel database più l'aspetto del peso, che sto bene con.

Ecco la mia dichiarazione SQL attuale, che prende anche il fattore del trasporto libero sopra un certo peso:

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
.

Quanto sopra tuttavia utilizza la funzione di sottostringa () con il numero di caratteri con codice duro impostato su 2 - questo è dove ho bisogno di aiuto davvero per farcela solo il numero di caratteri che corrisponde al codice postale fornito, in questo caso B1.

Marcus - Grazie per l'aiuto - Esempio eccezionale - Ecco ciò che sembra il mio codice per coloro che si chiedono anche:

Per prima cosa ho eseguito la seguente dichiarazione per ottenere il codice postale giusto:

(
    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
.

Quindi, in base al valore restituito assegnato all'indice 'Post_Code' la mia seconda istruzione seguita con:

$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
.

È stato utile?

Soluzione

The following query will get all results where the post_code in the shipping table matches the beginning of the passed in post_code, then it orders it most explicit to least explicit, returning the most explicit one:

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

Update

While this query is flexible, it's not very fast, since it can't utilize an index. If the shipping table is large, and you'll only pass in up to two characters, it might be faster to make two separate calls.

First, try the most explicit call.

SELECT *
FROM shipping
WHERE post_code = 'B1'

If it doesn't return a result then search on a single character:

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

Of course, you can combine these with a UNION if you must do it in a single call:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top