我试图查询一些格和逻辑,然后我得到一些长的数字,显然查询不喜欢这样。
假设我在数据库中有这些
Meta-key: lat
Meta-value: 54.3415000
Meta-key: lng
Meta-value: 10.1254100
然后执行如下查询:
$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\',
)
);
然后就行了,
BUT, 当它看起来像这样时:
$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\',
)
);
然后它就不起作用了,即使它仍然在两个数字之间。
有人知道这是怎么回事吗?一定是MYSQL的东西。
EDIT:
以下是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
SO网友:s_ha_dum
您的问题是:
CAST(wp_postmeta.meta_value AS SIGNED)
运行一个简单的SQL查询(命令行或PhpMyAdmin,无论您喜欢什么)
SELECT CAST(\'1.2\' as SIGNED)
您将看到返回的值是
1
. 是什么导致了这种情况
\'type\' => \'NUMERIC\',
.
你可以通过DECIMAL
到meta_query
而不是NUMERIC
但我看不到将参数传递给DECIMAL
这实际上会使它变得有用。SELECT CAST(\'1.2\' as DECIMAL)
也是1
除非您还将参数传递给DECIMAL
像这样SELECT CAST(\'1.2\' as DECIMAL(20,10))
. 第一个数字是“精度”——数学中使用的小数位数——第二个是返回的小数位数。在我看来,第二个值需要至少比第一个值小2,否则会出现奇怪的舍入问题。显然,第二个数字必须等于或大于数字中的最大小数位数。
最好的方法是\'type\' => \'DECIMAL\',
并应用过滤器:
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\');
在查询之前添加过滤器,它将删除自身。
你may 通过将数字填充到相同的长度,而不是使用type
这是一个争论,但我并没有对此进行测试。
SO网友:Amit
几年前,我使用了类似的东西,我最终使用了原始sql(不记得为什么),但我从您的原始sql和我的原始sql中看到的主要区别是这一行:
AND CAST(wp_postmeta.meta_value AS SIGNED) BETWEEN \'54.1833340338\'
在我的例子中,它被转换为十进制,值是数字(不是字符串):
AND CAST(wp_postmeta.meta_value AS DECIMAL(20,10)) BETWEEN 54.1833340338
而实际lat/lng没有单引号->所以它们是实际数字。
尝试运行以下操作:
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