gpt4 book ai didi

php - Wordpress 组合查询

转载 作者:可可西里 更新时间:2023-11-01 07:16:25 24 4
gpt4 key购买 nike

我有两个查询需要尝试合并,这样我的分页才能正常工作,并且帖子以正确的顺序显示。

我有一个问题:

$today = date('m/d/Y', strtotime('today'));

$args = array(
'post_type' => 'workshops',
"posts_per_page" => 5,
"paged" => $paged,
'meta_key' => 'select_dates_0_workshop_date',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'select_dates_0_workshop_date',
'meta-value' => "meta_value",
'value' => $today,
'compare' => '>=',
'type' => 'CHAR'
)
)
);

这个查询的结果需要在上面的查询之后:

$args = array(
'post_type' => 'workshops',
"posts_per_page" => 5,
"paged" => $paged,
'meta_key' => 'select_dates_0_workshop_date',
'orderby' => 'meta_value',
'order' => 'DESC',
'meta_query' => array(
array(
'key' => 'select_dates_0_workshop_date',
'meta-value' => "meta_value",
'value' => $today,
'compare' => '<',
'type' => 'CHAR'
)
)
);

这两个查询的区别在于:'order''compare'

我在纯 MYSQL 查询中完成了此操作,但我不确定如何在 WordPress 上执行此操作

最佳答案

这是答案的更新版本,比之前的版本更灵活。

下面是一个使用 SQL UNION 的想法:

  • 我们可以使用来自posts_clauses 过滤器的数据来重写来自posts_request 过滤器的SQL 查询。

  • 我们扩展 WP_Query 类来实现我们的目标。我们实际上做了两次:

    • WP_Query_Empty:获取每个子查询生成的SQL查询,但不做数据库查询。
    • WP_Query_Combine:获取帖子。
  • 下面的实现支持合并N个子查询。

这里有两个演示:

演示#1:

假设您有六个帖子,按日期 (DESC) 排序:

CCC
AAA
BBB
CCC
YYY
ZZZ
XXX

其中 XXXYYYZZZ 早于 DT=2013-12-14 13:03:40.

让我们对帖子进行排序,以便在 DT 之后发布的帖子按标题 (ASC) 排序,在 DT 之前发布的帖子按标题 (DESC) 排序:

AAA
BBB
CCC
ZZZ
YYY
XXX

然后我们可以使用以下内容:

/**
* Demo #1 - Combine two sub queries:
*/

$args1 = array(
'post_type' => 'post',
'orderby' => 'title',
'order' => 'ASC',
'date_query' => array(
array( 'after' => '2013-12-14 13:03:40' ),
),
);

$args2 = array(
'post_type' => 'post',
'orderby' => 'title',
'order' => 'DESC',
'date_query' => array(
array( 'before' => '2013-12-14 13:03:40', 'inclusive' => TRUE ),
),
);

$args = array(
'posts_per_page' => 1,
'paged' => 1,
'sublimit' => 1000,
'args' => array( $args1, $args2 ),
);

$results = new WP_Combine_Queries( $args );

这会生成以下 SQL 查询:

SELECT SQL_CALC_FOUND_ROWS * FROM ( 
( SELECT wp_posts.*
FROM wp_posts
WHERE 1=1
AND ( ( post_date > '2013-12-14 13:03:40' ) )
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_title ASC
LIMIT 1000
)
UNION
( SELECT wp_posts.*
FROM wp_posts
WHERE 1=1
AND ( ( post_date <= '2013-12-14 13:03:40' ) )
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_title DESC
LIMIT 1000
)
) as combined LIMIT 0, 10

演示#2:

这是你的例子:

/**
* Demo #2 - Combine two sub queries:
*/

$today = date( 'm/d/Y', strtotime( 'today' ) );

$args1 = array(
'post_type' => 'workshops',
'meta_key' => 'select_dates_0_workshop_date',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'select_dates_0_workshop_date',
'value' => $today,
'compare' => '>=',
'type' => 'CHAR',
),
)
);

$args2 = array(
'post_type' => 'workshops',
'meta_key' => 'select_dates_0_workshop_date',
'orderby' => 'meta_value',
'order' => 'DESC',
'meta_query' => array(
array(
'key' => 'select_dates_0_workshop_date',
'value' => $today,
'compare' => '<',
'type' => 'CHAR',
),
)
);

$args = array(
'posts_per_page' => 5,
'paged' => 4,
'sublimit' => 1000,
'args' => array( $args1, $args2 ),
);

$results = new WP_Combine_Queries( $args );

这应该给你一个这样的查询:

SELECT SQL_CALC_FOUND_ROWS * FROM ( 
( SELECT wp_posts.*
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 = 'workshops'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private')
AND (wp_postmeta.meta_key = 'select_dates_0_workshop_date' AND (mt1.meta_key = 'select_dates_0_workshop_date' AND CAST(mt1.meta_value AS CHAR) >= '05/16/2014') )
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value ASC
LIMIT 1000
)
UNION
( SELECT wp_posts.*
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 = 'workshops'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private')
AND (wp_postmeta.meta_key = 'select_dates_0_workshop_date' AND (mt1.meta_key = 'select_dates_0_workshop_date' AND CAST(mt1.meta_value AS CHAR) < '05/16/2014') )
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value DESC
LIMIT 1000
)
) as combined LIMIT 15, 5

演示#3:

我们还可以组合两个以上的子查询:

/**
* Demo #3 - Combine four sub queries:
*/

$args = array(
'posts_per_page' => 10,
'paged' => 1,
'sublimit' => 1000,
'args' => array( $args1, $args2, $args3, $args4 ),
);

$results = new WP_Combine_Queries( $args );

类:

这是我们的演示类(class):

/**
* Class WP_Combine_Queries
*
* @uses WP_Query_Empty
* @link https://stackoverflow.com/a/23704088/2078474
*
*/

class WP_Combine_Queries extends WP_Query
{
protected $args = array();
protected $sub_sql = array();
protected $sql = '';

public function __construct( $args = array() )
{
$defaults = array(
'sublimit' => 1000,
'posts_per_page' => 10,
'paged' => 1,
'args' => array(),
);

$this->args = wp_parse_args( $args, $defaults );

add_filter( 'posts_request', array( $this, 'posts_request' ), PHP_INT_MAX );

parent::__construct( array( 'post_type' => 'post' ) );
}

public function posts_request( $request )
{
remove_filter( current_filter(), array( $this, __FUNCTION__ ), PHP_INT_MAX );

// Collect the generated SQL for each sub-query:
foreach( (array) $this->args['args'] as $a )
{
$q = new WP_Query_Empty( $a, $this->args['sublimit'] );
$this->sub_sql[] = $q->get_sql();
unset( $q );
}

// Combine all the sub-queries into a single SQL query.
// We must have at least two subqueries:
if ( count( $this->sub_sql ) > 1 )
{
$s = '(' . join( ') UNION (', $this->sub_sql ) . ' ) ';

$request = sprintf( "SELECT SQL_CALC_FOUND_ROWS * FROM ( $s ) as combined LIMIT %s,%s",
$this->args['posts_per_page'] * ( $this->args['paged']-1 ),
$this->args['posts_per_page']
);
}
return $request;
}

} // end class

/**
* Class WP_Query_Empty
*
* @link https://stackoverflow.com/a/23704088/2078474
*/

class WP_Query_Empty extends WP_Query
{
protected $args = array();
protected $sql = '';
protected $limits = '';
protected $sublimit = 0;

public function __construct( $args = array(), $sublimit = 1000 )
{
$this->args = $args;
$this->sublimit = $sublimit;

add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), PHP_INT_MAX );
add_filter( 'posts_request', array( $this, 'posts_request' ), PHP_INT_MAX );

parent::__construct( $args );
}

public function posts_request( $request )
{
remove_filter( current_filter(), array( $this, __FUNCTION__ ), PHP_INT_MAX );
$this->sql = $this->modify( $request );
return '';
}

public function posts_clauses( $clauses )
{
remove_filter( current_filter(), array( $this, __FUNCTION__ ), PHP_INT_MAX );
$this->limits = $clauses['limits'];
return $clauses;
}

protected function modify( $request )
{
$request = str_ireplace( 'SQL_CALC_FOUND_ROWS', '', $request );

if( $this->sublimit > 0 )
return str_ireplace( $this->limits, sprintf( 'LIMIT %d', $this->sublimit ), $request );
else
return $request;
}

public function get_sql( )
{
return $this->sql;
}

} // end class

然后您可以根据需要调整类(class)。

我使用技巧 mentioned here保留 UNION 子查询的顺序。您可以使用我们的 sublimit 参数对其进行相应修改。

这也适用于主要查询,例如,通过使用 posts_request 过滤器。

希望对您有所帮助。

关于php - Wordpress 组合查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23555109/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com