J'essaie d'interroger un peu de lattitude et de logique, puis j'obtiens de longs chiffres et apparemment, l'interrogation n'aime pas cela.
Let dit que j'ai ceux-ci dans la base de données
Meta-key: lat
Meta-value: 54.3415000
Meta-key: lng
Meta-value: 10.1254100
et faites une requête comme celle-ci:
$args['meta_query'] =
array(
'relation' => 'AND',
array(
'key' => 'lat',
'value' => array( '53.82659686199116', '54.946076335668714' ),
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
),
array(
'key' => 'lng',
'value' => array( '8.429260683593725', '11.889954042968725' ),
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
)
);
Alors ça marche, MAIS, quand ça ressemble à ça:
$args['meta_query'] =
array(
'relation' => 'AND',
array(
'key' => 'lat',
'value' => array( '54.10933293482647', '54.66906633195788' ),
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
),
array(
'key' => 'lng',
'value' => array( '9.294434023437475', '11.024780703124975' ),
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
)
);
Ensuite, cela ne fonctionne pas, même s'il reste entre les 2 chiffres.
Quelqu'un a une idée de ce qui se passe ici? Ça doit être des trucs MYSQL.
EDIT:
Voici à quoi ressemble une requête mysql:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON
(wp_posts.ID = wp_postmeta.post_id)INNER JOIN wp_postmeta AS mt1 ON
(wp_posts.ID = mt1.post_id) WHERE 1=1 AND wp_posts.post_type = 'branchenbuch'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'future'
OR wp_posts.post_status = 'draft' OR wp_posts.post_status = 'pending'
OR wp_posts.post_status = 'private') AND ( (wp_postmeta.meta_key = 'lat'
AND CAST(wp_postmeta.meta_value AS SIGNED) BETWEEN '54.1833340338'
AND '54.4636527622')AND (mt1.meta_key = 'lng' AND CAST(mt1.meta_value AS SIGNED)
BETWEEN '9.76272625977' AND '10.6278995996') ) GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC LIMIT 0, 10
Votre problème est le suivant:
CAST(wp_postmeta.meta_value AS SIGNED)
Exécutez une requête SQL simple (ligne de commande ou PhpMyAdmin, comme vous voulez) comme SELECT CAST('1.2' as SIGNED)
et vous verrez que la valeur renvoyée est 1
. La cause de cette distribution est 'type' => 'NUMERIC',
.
Vous pouvez passer DECIMAL
à meta_query
au lieu de NUMERIC
mais je ne vois pas de moyen de passer des paramètres à DECIMAL
qui le rendrait utile. SELECT CAST('1.2' as DECIMAL)
est également 1
à moins que vous ne passiez également des arguments à DECIMAL
comme ceci SELECT CAST('1.2' as DECIMAL(20,10))
. Le premier nombre est "précision" - le nombre de décimales utilisées dans le calcul - et le second est le nombre de décimales renvoyées. La seconde me semble que la seconde valeur doit être au moins égale à 2 de moins que la première ou que vous rencontrez des problèmes d'arrondi bizarres. De toute évidence, la seconde doit être égale ou supérieure au maximum de décimales dans votre nombre.
Votre meilleure approche serait d’utiliser 'type' => 'DECIMAL',
et d’appliquer un filtre:
function add_decimal_params($sqlarr) {
remove_filter('get_meta_sql','add_decimal_params');
$sqlarr['where'] = str_replace('DECIMAL','DECIMAL(20,16)',$sqlarr['where']);
return $sqlarr;
}
add_filter('get_meta_sql','add_decimal_params');
Ajoutez le filtre immédiatement avant votre requête et il se supprimera.
Vous pouvez pouvoir le faire fonctionner en laissant à gauche vos nombres à la même longueur et ne pas utiliser d'argument type
du tout, mais je n'ai pas testé cela.
J'ai utilisé quelque chose de similaire il y a quelques années. J'ai finalement utilisé du SQL brut (je ne me souviens plus pourquoi), mais la principale différence que je vois entre votre SQL brut et le mien est la suivante:
AND CAST(wp_postmeta.meta_value AS SIGNED) BETWEEN '54.1833340338'
dans mon cas, il est converti en DECIMEL et les valeurs sont des nombres (pas des chaînes):
AND CAST(wp_postmeta.meta_value AS DECIMAL(20,10)) BETWEEN 54.1833340338
et les lat/lng réels sont sans guillemets simples -> ils sont donc des nombres réels.
Essayez de lancer ceci:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON
(wp_posts.ID = wp_postmeta.post_id)INNER JOIN wp_postmeta AS mt1 ON
(wp_posts.ID = mt1.post_id) WHERE 1=1 AND wp_posts.post_type = 'branchenbuch'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'future'
OR wp_posts.post_status = 'draft' OR wp_posts.post_status = 'pending'
OR wp_posts.post_status = 'private')
AND ( (wp_postmeta.meta_key = 'lat'
AND CAST(wp_postmeta.meta_value AS DECIMAL(20,10))
BETWEEN 54.1833340338 AND 54.4636527622)
AND (mt1.meta_key = 'lng'
AND CAST(mt1.meta_value AS DECIMAL(20,10))
BETWEEN 9.76272625977 AND 10.6278995996))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC LIMIT 0, 10