Campo de meta de consulta usando entre

3

Estoy tratando de consultar un poco de latitud y logitude y luego obtengo algunos números largos y aparentemente la consulta no me gusta.

Deja que diga que tengo esto en la base de datos

Meta-key: lat 
Meta-value: 54.3415000 
Meta-key: lng
Meta-value: 10.1254100

y haz una consulta como esta:

$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',
            )
        );

Entonces funciona, PERO , cuando se ve así:

$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',
            )
        );

Entonces no funciona, incluso si está entre los 2 números.

¿Alguien tiene una pista de lo que está pasando aquí? Debe haber algo de MYSQL.

EDIT:

Aquí es cómo se ve una solicitud de 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 
    
pregunta Kristian Primdal 01.02.2013 - 17:03

2 respuestas

1

Tu problema es este:

CAST(wp_postmeta.meta_value AS SIGNED)

Ejecuta una consulta SQL simple (línea de comandos o PhpMyAdmin, como quieras) como SELECT CAST('1.2' as SIGNED) y verás que el valor devuelto es 1 . Lo que causa ese lanzamiento es 'type' => 'NUMERIC', .

Puedes pasar DECIMAL a meta_query en lugar de NUMERIC , pero no veo una manera de pasar parámetros a DECIMAL que realmente lo haría útil. SELECT CAST('1.2' as DECIMAL) también es 1 a menos que también pases argumentos a DECIMAL como este SELECT CAST('1.2' as DECIMAL(20,10)) . El primer número es "precisión", el número de decimales utilizados en las matemáticas, y el segundo es el número de decimales devueltos. El segundo me parece que el segundo valor debe ser al menos 2 menos que el primero o que tenga problemas de redondeo impares. Obviamente, el segundo debe ser igual o mayor que los decimales máximos en su número.

Su mejor enfoque sería utilizar 'type' => 'DECIMAL', y aplicar un filtro:

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');

Agregue el filtro inmediatamente antes de su consulta y se eliminará.

Usted may podrá hacer que esto funcione a la izquierda rellenando sus números a la misma longitud y sin usar un argumento type en absoluto, pero no lo hice. No pruebes eso.

    
respondido por el s_ha_dum 01.12.2013 - 18:42
0

Usé algo similar hace un par de años, finalmente usé sql sin formato (no recuerdo por qué), pero la principal diferencia que veo en tu sql sin formato y en la mía es esta fila:

AND CAST(wp_postmeta.meta_value AS SIGNED) BETWEEN '54.1833340338' 

en mi caso, se convierte a DECIMEL y los valores son números (no cadenas):

AND CAST(wp_postmeta.meta_value AS DECIMAL(20,10)) BETWEEN 54.1833340338 

y la lat / lng real son sin comillas simples - > entonces son números reales.

Intenta ejecutar esto:

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 
    
respondido por el Amit 06.07.2013 - 20:24

Lea otras preguntas en las etiquetas