我想做一个复合查询,请教如何实现./****
表名:news                                表名:news_cate
news_id 编号                                newscate_id
news_title 标题                             news_cate_title 
news_info 信息  
news_cid  类别
news_date  日期 (Y-m-d H:i:s)
*****/我希望实现 
新闻标题news_title 的 like 查询  news_title like '%search_info%'
新闻内容 news_info 单选 为空 ,不为空查询 news_info is null , news_info is not null
新闻类别查询 复选   {假设类别为:1 实时新闻,2 历史事件 3专题报道} 当复选 1 3 时 (news_cid = 1 or news_cid = 3)
日期开始时间
日期结束时间设定也就是说,
当我标题搜索 “测试“ 内容 单选选 为空  ,类别复选选中  2 历史事件 3 专题报道后。  开始时间填写 2010-4-1 结束时间填写 2010-5-1 
查询后 sql 语句为
select * from news where news_title like '%测试%' and news_info is null  and news_date > '2010-4-1' and news_date < '2010-5-1'问题一: 请问这个复合查询,如何能封装成可复用的。 我想做一个复合查询,请教如何实现./****
表名:news                                表名:news_cate
news_id 编号                                newscate_id
news_title 标题                             news_cate_title 
news_info 信息  
news_cid  类别
news_date  日期 (Y-m-d H:i:s)
*****/我希望实现 
新闻标题news_title 的 like 查询  news_title like '%search_info%'
新闻内容 news_info 单选 为空 ,不为空查询 news_info is null , news_info is not null
新闻类别查询 复选   {假设类别为:1 实时新闻,2 历史事件 3专题报道} 当复选 1 3 时 (news_cid = 1 or news_cid = 3)
日期开始时间
日期结束时间设定也就是说,
当我标题搜索 “测试“ 内容 单选选 为空  ,类别复选选中  2 历史事件 3 专题报道后。  开始时间填写 2010-4-1 结束时间填写 2010-5-1 
查询后 sql 语句为
select * from news where news_title like '%测试%' and news_info is null  and news_date > '2010-4-1' and news_date < '2010-5-1'问题一: 请问这个复合查询,如何能封装成可复用的。例如能通过很方便的配置 news_title 的查询规则变一下,变为 news_title = '测试'
问题二: 查询完了后,数据很多时,会产生分页。 假设有五页结果,当我点第三页时,我希望查询条件还能保留问题二: 查询完了后,数据很多时,会产生分页。 假设有五页结果,当我点第三页时,我希望查询条件还能保留

解决方案 »

  1.   


    /*********
     * 帶參數的查詢.
     *********/
    //餐廳區域
    $layout_id=isset($_GET["layout_id"])?intval($_GET["layout_id"]):'';
    $table_state=isset($_GET["table_state"]) && intval($_GET["table_state"])>0?intval($_GET["table_state"]):'';
    $where="where 1";
    $where.=!empty($layout_id)?" AND table_layout_id=$layout_id":'';
    $where.=!empty($table_state)?" AND table_state=$table_state":''; $sql_table="SELECT t.table_id,t.opentable_id,t.table_number,t.table_name,t.table_layout_id,t.table_room_layout_id,t.table_sum,t.table_state,l.layout_name FROM `tables` as t left join layouts l on t.table_layout_id=l.layout_id $where order by t.table_id asc";
    // echo $sql_table;
      

  2.   

    问题1: 封装成一个函数,
     // $hasInfo : 传入news_info是否为空
     //$ids : 想要获得新闻 ids 
     //return 查询的结果集
     function getRecords($hasInfo,$ids,$timeFrom,$timeTo ){
         $con = news_info . ($hasTitle ? 'is not null ' : 'is null') ;
         $con .= " AND news_date > $timeFrom AND news_date < $timeTo ";
         $sql = "select * from news where news_id IN ($ids) AND  $con ";
         //执行查询
          //return 查询结果 
    }
    由于查询条件需要用户输入,所以封装参数必须自行处理.
     
    问题2:
      写个分页类,共多少记录,每页多少记录,可以求出当前页的记录数.
         
      

  3.   

    把二楼的这几个东西做成函数接口:
    <?php
    function makeSql($_layout_id, $_table_state, $value=null) {

    $layout_id=isset($_layout_id)?intval($_layout_id):$value;
    $table_state=isset($_table_state) && intval($_table_state)>0?intval($_table_state):$value;
    $where="where 1";
    $where.=!empty($layout_id)?" AND table_layout_id=$layout_id":'';
    $where.=!empty($table_state)?" AND table_state=$table_state":'';
    $sql_table="SELECT t.table_id,t.opentable_id,t.table_number,t.table_name,t.table_layout_id,t.table_room_layout_id,t.table_sum,t.table_state,l.layout_name FROM `tables` as t left join layouts l on t.table_layout_id=l.layout_id $where order by t.table_id asc";
    return $sql_table;
    }
    ?>
      

  4.   

    这和接口有啥关系,这就是一个普通的成生sql 的函数.
    function makeSql($where,$table)
    {
    $sql  = "select * from table ";
    if($isset($where )&& sizeof($where)) {
    $sql .= "where 1=1";
    }
    foreach($where as $val)
    {
    $sql .= "&& $val";
    }
    return $sql;
    }
    这看来看去,只是一个普通的把查询条件和表名生成sql 语句的函数。
    请问楼上,何来接口之说,如果真有接口,具体是怎么个接法。感觉楼上的回答很缥缈,难以理解,望回答的实在点。
      

  5.   

    传参数,将sql语句反回就可以了。。
      

  6.   

    借楼主的想法讲开去。楼主的想法,
    1 表单提交后 能通过表单的内容自动的生成sql语句,并查询相应的数据.
    2 通过点击分页,也能生成sql 语句,并且记录了之前表单的查询结果。那这种情况下,楼主希望有这样一种代码。   $myList = new xList();
       $myList->setTable($this->tableName);
       $myList->setIQuery(new adminIQuery());
       list($data["pager"],$data['rows']) = $myList->get();  //获取数据
    //当设置好所对应的表格(model) ,
    //Iquery 接口。[将post 或querystring 的参数,生成查询条件,并得到用于拼值QueryString 的参数]
    $this->load->view('admin/'.$this->tableName.'/index', $data);
    通过上述代码,就能把post 的值,或get 的QueryString 生成相应的查询语句,并查询出列表数据,和分页栏数据,然后交由视图合成界面。
      

  7.   

    楼上好几位兄弟都也是说要生成sql语句。 
    但他们给出的代码不能太过简单。
    如果有很多情况都不知道如何去处理,
    例如是复选情况下的搜索,怎么去解决,
    如果搜索的条件是is null 如何去处理,
    如果我需要的是复合查询更极端的例子呢? 例如,我希望查询 其中一个字段 等于另外两个字段的合的例子。还有个令我很头痛的问题,一直没怎么想通,怎么样方便的把查询条件存在分页栏的queryString 上呢?
      

  8.   

    我希望实现  
    新闻标题news_title 的 like 查询 news_title like '%search_info%'
    新闻内容 news_info 单选 为空 ,不为空查询 news_info is null , news_info is not null
    新闻类别查询 复选 {假设类别为:1 实时新闻,2 历史事件 3专题报道} 当复选 1 3 时 (news_cid = 1 or news_cid = 3)
    日期开始时间
    日期结束时间设定
    --------------------------------------------------------------------------------<form action="#" id="form" name="formName" method="get">
      新聞標題:<input type="text" name="new_title" value="<?=$new_title?>" />
      內容選擇:<input type="radio" name="new_content" value="1" />不為空&nbsp
               <input type="radio" name="new_content" value="2" />為空&nbsp
      新聞類別:<input type="checkbox" name="new_type" value="1">類別1
               <input type="checkbox" name="new_type" value="2">類別2
               <input type="checkbox" name="new_type" value="3">類別3
      时间范围:从<input type="text" name="begin_time" value="<?=$begin_time?>">到<input type="text" name="end_time" value="<?=$end_time?>">
    </form>
      $new_title=isset($_GET["new_title"])?$_GET["new_title"]:'';
      $where =" where 1";
      $where.=(!empty($new_title))?" and news_title like '%$new_title%'":""
       .....分页部分..你只要将get参数保持在url上.就不会丢失...
    找个分页类.
      

  9.   

    楼上的,1将查询条件又搞死成 like 查询了,这不是楼主的本意。
    这情部下 生成的where 条件中的是 like 还是 = 还是 in() 是有变化的,这个就因当在表单这块就准备好。
     2分页部分,肯定是将get参数保存在url 上,就是这么解决的。针对1, 需要一个专门负责将 post 参数,和get 参数转换成 where 和保存为 queryString 的接口。
    为什么写成接口了。 不同的表单构造方式,不同的转换规则时,就用接口来实现了。
    针对2 还是那个接口,将传来的参数,暂存,并设置到分页所带的queryString中去。下面我贴点我以前在一个项目中完成的和这相关的代码,我尽量把里面的东西精简,已表达意思,希望对楼主有帮助。。/**
     * * 数据列表类.
     *
     */
    class xList
    {
        public static $CI = NULL;          //CI对象的实例
    private $table;
    private $where;
    private $parameters;  //当前分页数,和查询条件,都在parameters 中.
    private $rows;       //查询结果集
    private $pageSize = 10;
    private $pageData;
    public $IQuery;

    function xList()
    {
     $this->CI = &get_instance(); //取得CI对象的实例
    } /**
     * *设置表格
     *
     * @param unknown_type $tableName
     */
    function setTable($tableName)
    {
    $this->table = $tableName;
    }

    /**
     * * 设置查询分页解析接口
     *
     * @param IsearchQuery $Iseach
     */
    function setIQuery(IQuery $IQuery)
    {
    $this->IQuery = $IQuery;
    }

    /**
     * *
     *
     */
    function get()
    {
    //获取查询条件数组,和queryString 参数,并对参数的值进行处理.
    list($this->where,$this->parameters) = $this->IQuery->handleparameters();  

         /**加载模型*/
    $model_name = CS_get_model_name($this->table); //取得模型名称
    $this->CI->load->model($model_name);                    //加载模型. $this->getPager();
    $this->getRows();
       
    return array($this->pageData,$this->rows);
    }

    /**
     * * 获取分页数据
     *
     */
    function getPager()
    {
    $pagesize = $this->parameters["pagesize"];
    $offset = ($this->parameters["page"] - 1) * $pagesize;

    $model_name = CS_get_model_name($this->table); //取得模型名称
    $page_parameters = array(
    "recordcount" => $this->CI->$model_name->get_count($this->where), //总页数
    "pagesize"   => $pagesize //每页显示的记录数
    );

    $this->CI->load->library("pager", $page_parameters);
        
    /**添加button 按钮*/
    if(isset($this->CI->buttons) && sizeof($this->CI->buttons)){
    foreach ($this->CI->buttons as $button){
    $this->CI->pager->addButton($button);
    }
    }

    $this->CI->pager->setPath("admin/".$this->table."/index");
    unset($this->parameters['page']); //删除参数中的分页参数
    $this->CI->pager->setParamters($this->parameters); //设置分页链接中需要带的参数
    $this->pageData = $this->CI->pager->display(); //取得分页的HTML
    }

    /**
     * * 获取查询数据集
     *
     */
    function getRows()
    {
    $pagesize = $this->parameters["pagesize"];
    $offset = ($this->parameters["page"] - 1) * $pagesize; $model_name = CS_get_model_name($this->table); //取得模型名称
    $this->rows = $this->CI->$model_name->get($this->where,$pagesize,$offset);  //稍后加上分页大小
    }

    /***
               更多代码,省略
           */

    }
    //这样一来,关健的就是IQuery 的实现了,获取查询条件,和得到相应的参数的处理了。
    list($this->where,$this->parameters) = $this->IQuery->handleparameters();
    $this->CI->pager->setParamters($this->parameters);  //这句用来实现将查询条件存至分页栏.<?php
    interface IQuery
    {
    function handleparameters();
    function getConfigSearch($configSearch);
    }
    class adminIQuery implements IQuery
    {
    public static $CI;
    private $regeMap = array(
    "QueryEqual"=>"handleEqual"
    ,"QueryLike"=>"handleLike"
    ,"QueryNull"=>"handleNull"
    ,"QueryMult"=>"handleMult"
    );

    private $where = array();
    private $parameters = array();
    private $multJoinTag = "__xyx__"; //checkbox 多项搜索时,用于拼接成queryString 的间隔符
    private $indexDeep = 4;  //deep 深度 例如 http://demo/index.php/admin/menu/index 为4

    /**
     * * 实现getparameters 接口
     *
     */
    function handleparameters()
    {
    /*
    ///////////////////////////////////////////////////////////////////////////////
    解析模式说明.
    QueryEqual_Key  = $VAL;  例如 QueryEqual_menu_title  = 理  则表式对 menu_title 进行 = 查询
    QueryLike_Key  = $VAL;   例如 QueryLike_menu_title  = 理  则表式对 menu_title 进行 like 查询
    QueryNull_key = $VAL;    例如 QueryNullmenu_title = 1 ($val 值为1 时) 查询menu_title is null 为0 时查询menu_title is not null 
    QueryMult_key = $VAL;    例如 QueryNullmenu_cid = array(1,2) 则查询  menu_cid in (1,2)
    ///////////////////////////////////////////////////////////////////////////////
    */
    if(CS_is_post()){
    //分页参数的处理,如果同有相关参数,则设为1.
            $this->parameters["page"] = 1;    //post 搜索时,将page 置为第一页.   
            if($_POST["pagesize"] && is_numeric($_POST["pagesize"])) 
    {
    $this->parameters["pagesize"] = $_POST["pagesize"];      

    $this->handleArrayParam($_POST);


    }else {
    $this->CI = &get_instance(); //取得CI对象的实例
    $this->parameters = $this->CI->uri->uri_to_assoc($this->indexDeep); //解析URI中的参数
    $this->RhandleArrayParam($this->parameters);
    }

    //返回相应的值.
           return array($this->where,$this->parameters);
    }

    /**
     * * 实现通过queryString 和表名,获取搜索值的接口.
     */
    function getConfigSearch($configSearch)
    {

    foreach ($configSearch as $key=>$val):

    foreach ($this->parameters as $param_key=>$param_val):
    $pattern = "/".$val["search_type"]."/";

    if(preg_match($pattern,$param_key))
    {
    $handleMergeFunction = "merge".$val["search_type"];
    $configSearch[$key] =  $this->$handleMergeFunction($val,$param_val);

    }

    endforeach;
    endforeach;
    return $configSearch;
    }
    /***
     *处理数组的相关参数 搜索相关的参数,写到相应的 $this->paramters 和 $this->where 中去 
     */
    function handleArrayParam($post)
    {

    foreach ($post as $key=>$val):
    foreach ($this->regeMap as $regeKey =>$regeVal): //匹配规则.

    $pattern = "/".$regeKey."/";

    if(preg_match($pattern,$key))
    {
    $this->$regeVal($key,$val);
    }else {
    continue;
    }
    endforeach;
    endforeach;
    }

    function  RhandleArrayParam($array)
    {

    foreach ($array as $key=>$val):
    foreach ($this->regeMap as $regeKey =>$regeVal): //匹配规则.

    $pattern = "/".$regeKey."/";
    if(preg_match($pattern,$key))
    {
    $regeVal = "R".$regeVal;
    $this->$regeVal($key,$val);
    }else {
    continue;
    }
    endforeach;
    endforeach;
    }
    /**
     * *
     *
     * @param get方式接收的深度 $indexDeep
     */
    function setIndexDeep($indexDeep)
    {
    $this->indexDeep = $indexDeep;
    }/**
     * **查询参数处理集
     *
     * @param unknown_type $key
     * @param unknown_type $val
     */
    ////////////////////模糊查询 ////////////////////////////////////////////////////
    function handleLike($key,$val){   //post 方式 get 解析
    if($this->checkValNotNull(&$val)) {
     $key_title = str_replace("QueryLike_","",$key);  //找出mul 部分.
     $this->parameters += array_map('base_encode', array($key=>"$val"));
          $this->where[]= "($key_title  like '%$val%')";
    }
    }
    function RhandleLike($key,$val){  
    if($this->checkValNotNull(&$val)) {
    $val = base_decode($val);
      $key_title = str_replace("QueryLike_","",$key);  //找出mul 部分.
      $this->where[]= "($key_title  like '%$val%')";
    }
    }

    ////////////////////等值搜索 ////////////////////////////////////////////////////
    function handleEqual($key,$val)
    {

    if($this->checkValNotNull(&$val)) {
        $key_title = str_replace("QueryEqual_","",$key);  //找出mul 部分.
    $this->parameters += array_map('base_encode', array($key=>"$val"));
        $this->where[]= "($key_title = '$val')";
    }
    }
    function RhandleEqual($key,$val){  
    if($this->checkValNotNull(&$val)) {
        $val = base_decode($val);
      $key_title = str_replace("QueryEqual_","",$key);  //找出mul 部分.
      $this->where[]= "($key_title  = '$val')";
    }
    }
    ////////////////////复选框搜索 ////////////////////////////////////////////////////
    function handleMult($key,$val){
    echo "here";
    if(is_array($val) && sizeof($val))  //去除零选中状态.
    {
    $key_title = str_replace("QueryMult_","",$key);  //找出mul 部分.
        foreach($val as $val_piece)
    {
    $str_val[]= base_encode($val_piece);  //生成parm所用参数数组.

    }
    $str_mult = implode( $this->multJoinTag, $str_val );  
    $this->parameters[$key] = $str_mult; //合并生成parameters.
    $this->where []= "($key_title in(".implode(",",$val)."))";  //合并生成查询条件.   
    }
    }
    function RhandleMult($key,$val){  //通get方式传参进行转换
    $val = trim($val);
    if($val) {


    $key_title = str_replace("QueryMult_","",$key);  //找出mul 部分.
    $this->parameters[$key] = $val; //合并生成parameters.
    $item_array = explode($this->multJoinTag,$val);
    $item_array = array_map("base_decode",$item_array);
    $this->where []= "($key_title in(".implode(",",$item_array)."))";  //合并生成查询条件.   
    }
    }
    ////////////////////判断is null ////////////////////////////////////////////////////
    function handleNull($key,$val){

    $key_title = str_replace("QueryNull_","",$key);  //找出mul 部分.
    $this->parameters += array_map('base_encode', array($key=>"$val"));
    if($val)   $this->where[]= "($key_title is NULL)";
    else $this->where[]= "($key_title is not NULL)";

    }
       function RhandleNull($key,$val){ 
               $val = base_decode($val);
            $key_title = str_replace("QueryNull_","",$key);  //找出mul 部分.
    if($val)   
    {
    $this->where[]= "($key_title is NULL)";
    }
    else
    {
    $this->where[]= "($key_title is not NULL)";
    }
    }

    function checkValNotNull(&$val){ //空值判断
    $val = trim($val);
    return $val;
    }
       

    }