最新消息:文章中包含代码时,请遵守代码高亮规范!

[项目实战][原创]查询数据集的SQL直接变为查询数据集总数的SQL

PHP Jay 348浏览 0评论

方法适用注意:

1:方法默认sql的最后是 ORDER BY 及 LIMIT,使得分组查询,联合查询或着不满足该原则的高级SQL语句都无法进行正确转化。

class Sql
{

    /**
     * 得到总数sql
     *
     * @param $sql_list
     * @return mixed
     * @throws Exception
     */
    public function getCountSql($sql_list)
    {
        //得到有效的FROM
        $brackets_array = $this->getStrBracketsPositionArray($sql_list);
        $from_array = $this->getStrAppearAllPositionArray($sql_list, 'from');
        $from_tag = $this->getFirstNotArrayBetweenitem($brackets_array, $from_array);  //取出合适的FROM
        if($from_tag !== false){
            //判断是否为子查询--找到from—tag最近的一个()组合
            $tag = array();
            foreach ($brackets_array as $index => $value){
                if($index == 0){
                    if($from_tag < $value[0]){
                        //返回
                        $tag = $value;
                        break;
                    }
                }else{
                    if($brackets_array[$index-1][1] < $from_tag && $value[0] > $from_tag){
                        //返回
                        $tag = $value;
                        break;
                    }
                }
            }

            //如果找到标记组合,并且和FROM 标记之间由空格组成 则可判断存在子查询
            if(!empty($tag) &&  str_replace(' ','',substr($sql_list, $from_tag + 4, $tag[0] - $from_tag - 4)) == ''){
                $sql_list = substr($sql_list, $tag[0] + 1, $tag[1] - $tag[0] -1 );
                return $this->getCountSql($sql_list);
            }

            $order_by_tag = strripos($sql_list, 'order by');
            if($order_by_tag === false){
                $order_by_tag = strripos($sql_list, 'limit');
                if($order_by_tag === false) {
                    $order_by_tag = strlen($sql_list);
                }
            }
            if($order_by_tag < $from_tag){ $order_by_tag = strlen($sql_list); } $group_tag = strripos($sql_list, 'group by'); if($group_tag !== false){ $sql = "SELECT count(*) as total_record_num FROM ({$sql_list}) AS count_table"; }else{ $sql = 'SELECT COUNT(*) ' . substr($sql_list, $from_tag, $order_by_tag - $from_tag); } return $sql; }else{ throw new Exception('SQL错误:'.$sql_list); } } /** * 得到总数 * * @param $sql * @return mixed */ public function getCount($sql) { return self::$conn->fetchColumn($this->getCountSql($sql));
    }


    /**
     * 得到字符串中括号的数组
     *
     * @param $str
     * @return array
     */
    public function getStrBracketsPositionArray($str)
    {
        $str_array = str_split($str);

        //得到括号的数组
        $brackets_array = [];
        $i = 0;
        $tag_array = array();
        foreach ($str_array as $index => $value){
            if($value == '('){
                $brackets_array[$i][0] = $index;
                array_unshift($tag_array, $i);
                $i++;
            }
            if($value == ')'){
                $brackets_array[$tag_array[0]][1] = $index;
                array_shift($tag_array);
            }
        }

        return $brackets_array;
    }

    /**
     * 得到一个字符串在另外一个字符串中的全部位置
     *
     * @param $str
     * @param $lookup_str
     * @return array
     */
    public function getStrAppearAllPositionArray($str, $lookup_str)
    {
        $str = strtolower($str);

        $count = substr_count($str,  $lookup_str);

        $arr = array();
        $j = 0;
        for($i = 0; $i < $count; $i++){ 
            $j = strpos($str, $lookup_str, $j); $arr[] = $j; $j = $j+1; 
        } 
       return $arr; 
   } 

/**
 * 查询子数据成员不在主数据成员两者之间, 返回第一个满足情况的内容 
 * 
 * @param $main_array 
 * @param $lookup_array 
 * @return int 
 */ 
public function getFirstNotArrayBetweenitem($main_array, $lookup_array) 
{ 
         $brackets_array_count = count($main_array); 
         foreach ($lookup_array as $index => $value){
            $j = 0;
            for ($i = 0; $i < $brackets_array_count; $i++){ if($value > $main_array[$i][0] && $value < $main_array[$i][1]){
                    $j = 1;
                    break;
                }
            }
            if($j == 0){
                return $value;
            }
        }

        return false;
    }

}

转载时请注明出处及相应链接,本文永久地址:https://blog.yayuanzi.com/23366.html


pay_weixin
pay_weixin
微信打赏
pay_weixin
支付宝打赏
感谢您对作者Jay的打赏,我们会更加努力!    如果您想成为作者,请点我

您必须 登录 才能发表评论!