【问题标题】:Preg_replace() removing all but the end of queryPreg_replace() 删除除查询结束之外的所有内容
【发布时间】:2014-07-02 18:08:54
【问题描述】:

首先,对不起我的英语不好。

我有这个问题:

SELECT t1.*,(SELECT COUNT(*) FROM table_a t2 WHERE t1.id=t2.id_c AND t2.status=1) AS aula 
FROM table_c t1 
WHERE t1.status=1 
AND t1.id IN (SELECT t3.id_c FROM table_cu t3 WHERE t3.id_c=t1.id AND t3.id_u=1) 
AND t1.id IN (SELECT t4.id_c FROM table_cp t4 WHERE t4.id_c=t1.id AND t4.id_p=3) 
LIMIT 0,25

这个查询返回给我一组结果,直到现在没有问题,但是我有一个分页类,它有一个非常基本的过程:它计算我得到了多少条目,然后将条目分成几部分,然后用这个值我分页。

问题出在“分页类”的这个方法中,代码如下:

function total_entries()
{

    $db = new db(DB_USER, DB_PASS, DB_NAME, DB_HOST);

    $qtdEntries = 0;

    $queryQtd = $this->sql;
    $queryQtd = preg_replace("/SELECT (.*) FROM /sei", "'SELECT COUNT(*) as qtd FROM '", $queryQtd);
    $queryQtd = preg_replace("/ORDER BY (.+)/", "", $queryQtd);
    $queryQtd = preg_replace("/LIMIT (.+)/", "", $queryQtd);

    $resultAll = $db->get_row($queryQtd); //Gets the result, in this case, it returns the number of entries

    if($resultAll){
        $qtdEntries = $resultAll->entries; //Number of entries
    }

    return $qtdEntries;
}

基本上当我运行这个方法时,它里面的查询返回如下:

SELECT COUNT(*) as qtd FROM table_cp t4 WHERE t4.id_c=t1.id AND t4.id_p=3)

什么时候应该返回如下内容:

SELECT COUNT(*) as qtd FROM table_c t1 WHERE t1.status=1

任何想法如何纠正这个问题?

【问题讨论】:

  • 我只是不明白,你想做什么,但也许SQL_CALC_FOUND_ROWS 与函数FOUND_ROWS 结合使用可以更好地实现分页目标。
  • 好的,让我试着解释一下:我有一个查询,我想计算它返回给我的行数,如果可能的话,使用接近我已有的数据。
  • 如果您使用的是LIMIT 子句,则只需将SQL_CALC_FOUND_ROWSSELECT FOUND_ROWS(); 结合使用。如果您不使用LIMIT 子句,则只需使用子选择SELECT COUNT(*) FROM (your first query goes here)。如果您的查询速度很慢,那么这种(和您的)方法将使问题加倍。
  • 您能否使用我帖子的第一个查询来发布我如何使用SQL_CALC_FOUND_ROWSFOUND_ROWS(),以便我可以将您的答案标记为正确?谢谢。
  • 我不知何故忽略了您的原始查询。您确实遇到的问题是模式的贪婪。模式尽可能匹配,因此只匹配WHERE 子句中的子选择

标签: php mysql regex pagination


【解决方案1】:

解决此问题的更好方法是使用 MySQL 的内置功能:

您只需在SELECT 关键字后添加SQL_CALC_FOUND_ROWS 并结合函数FOUND_ROWS

SELECT SQL_CALC_FOUND_ROWS t1.*,(SELECT COUNT(*) FROM table_a t2 WHERE t1.id=t2.id_c AND t2.status=1) AS aula 
FROM table_c t1 
WHERE t1.status=1 
AND t1.id IN (SELECT t3.id_c FROM table_cu t3 WHERE t3.id_c=t1.id AND t3.id_u=1) 
AND t1.id IN (SELECT t4.id_c FROM table_cp t4 WHERE t4.id_c=t1.id AND t4.id_p=3) 
LIMIT 0,25

如果没有LIMIT 子句,要获取行数,现在可以使用语句

SELECT FOUND_ROWS();

作为下一个查询。

正则表达式方法的问题在于正确使用正则表达式。匹配通常是贪心的,它会尽可能匹配。在这种情况下,它只会匹配WHERE 子句的最后一个条件,因为此条件使用带有FROM 关键字的子选择。因为这个模式

SELECT (.*) FROM

$queryQtd = preg_replace("/SELECT (.*) FROM /sei", "'SELECT COUNT(*) as qtd FROM '", $queryQtd);

匹配的远不止 SELECT 的字段列表(也包含带有 FROM 的子选择)。

【讨论】:

    猜你喜欢
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多