使用条件语句的高级SELECT查询

时间:2014-09-12 作者:Nathan

我很难理解编写高级select查询的正确方法。我这里有以下代码。

if (!empty($_GET[\'3321body_type\'])) {
    $bt = $_GET[\'3321body_type\'];
    $bt_sql = "AND m1.meta_key = \'body_type\' AND m1.meta_value = \'$bt\'";
}
else $bt_sql = \'\';
if (!empty($_GET[\'3321Make\'])) {
   $make = $_GET[\'3321Make\'];
    $make_sql = "AND m3.meta_key = \'Make\' AND m3.meta_value = \'$make\'";
}
 else $make_sql = \'\';   
    if (!empty($_GET[\'3321Model\'])) {
        $model = $_GET[\'3321Model\'];
    $model_sql = "AND m4.meta_key = \'Model\' AND m4.meta_value = \'$model\'";
    }
   else $model_sql = \'\';
  if (!empty($_GET[\'3321Year\'])) {
  $year = $_GET[\'3321Year\'];
  $year_sql = " AND m2.meta_key = \'Year\' AND m2.meta_key = \'Year\' AND   
  m2.meta_value       BETWEEN \'$year\' AND \'9999\'";

  }
  else $year_sql = \'\'; 
   global $wpdb;
    $wpdb->show_errors = true;

$querystr = "
SELECT * FROM wp_posts
LEFT JOIN wp_postmeta m0 on (wp_posts.ID = m0.post_id) 
LEFT JOIN wp_postmeta m1 on (wp_posts.ID = m1.post_id) 
LEFT JOIN wp_postmeta m2 on (wp_posts.ID = m2.post_id) 
LEFT JOIN wp_postmeta m3 on (wp_posts.ID = m3.post_id) 
LEFT JOIN wp_postmeta m4 on (wp_posts.ID = m4.post_id) 
WHERE wp_posts.ID = m0.post_ID
" . $bt_sql . "
" . $make_sql . "
" . $model_sql . "
" . $year_sql . "
";

$search = $wpdb->get_results($querystr, OBJECT);
foreach($search as $post) {
setup_postdata($post);
如果我这样写出来

SELECT * FROM wp_posts
LEFT JOIN wp_postmeta m0 on (wp_posts.ID = m0.post_id) 
LEFT JOIN wp_postmeta m1 on (wp_posts.ID = m1.post_id) 
LEFT JOIN wp_postmeta m2 on (wp_posts.ID = m2.post_id) 
LEFT JOIN wp_postmeta m3 on (wp_posts.ID = m3.post_id) 
LEFT JOIN wp_postmeta m4 on (wp_posts.ID = m4.post_id) 
WHERE wp_posts.ID = m0.post_ID
AND m1.meta_key = \'body_type\' AND m1.meta_value = \'Sedan\'
AND m3.meta_key = \'Make\' AND m3.meta_value = \'Acura\'
AND m4.meta_key = \'Model\' AND m4.meta_value = \'CL\'
AND m2.meta_key = \'Year\' AND m2.meta_key = \'Year\' AND m2.meta_value BETWEEN \'$year\' AND \'9999\'
结果很好。但当我在第一段代码中添加条件语句时。连接似乎工作不正常,因为它返回重复的行。

谁能告诉我如何正确地编写此语句以使搜索查询动态化?这也是一个如何在工程中使用wpdb->prepare的示例。

1 个回复
最合适的回答,由SO网友:Rarst 整理而成

我认为您使用自定义SQL是在开玩笑,其复杂性似乎仍在WP_Query. 即使不是这样,也最好从它开始,为自定义SQL提供更坚实的基础。

如果我尝试这样的方法:

$meta_query = array(
    array( \'key\' => \'body_type\', \'value\' => \'bt\' ),
    array( \'key\' => \'Make\', \'value\' => \'make\' ),
    array( \'key\' => \'Model\', \'value\' => \'model\' ),
    array( \'key\' => \'Year\', \'value\' => array( 2010, 9999 ), \'compare\' => \'BETWEEN\' ),
);

$query = new WP_Query( array( \'meta_query\' => $meta_query ) );

$query->get_posts();
var_dump( $wpdb->queries );
这是生成的SQL:

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)
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id)
INNER JOIN wp_postmeta AS mt3 ON (wp_posts.ID = mt3.post_id)
WHERE 1=1
  AND wp_posts.post_type = \'post\'
  AND (wp_posts.post_status = \'publish\'
       OR wp_posts.post_status = \'private\')
  AND ((wp_postmeta.meta_key = \'body_type\'
        AND CAST(wp_postmeta.meta_value AS CHAR) = \'bt\')
       AND (mt1.meta_key = \'Make\'
            AND CAST(mt1.meta_value AS CHAR) = \'make\')
       AND (mt2.meta_key = \'Model\'
            AND CAST(mt2.meta_value AS CHAR) = \'model\')
       AND (mt3.meta_key = \'Year\'
            AND CAST(mt3.meta_value AS CHAR) BETWEEN \'2010\' AND \'9999\'))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC LIMIT 0, 10
请注意GROUP BY 最后,它可能会处理您正在获得的副本。

看见Custom Field Parameters 有关元查询的更多信息,请参阅Codex中的文档。

结束