sql查询语句如何解析成分页查询?

我们公司主要mysql存储数据,因此也封装了比较好用mysql通用方法,然后,我们做大量接口,在处理分页查询接口,没有很好分查询方法。sql查询 语句如何解析成“分页查询”和“总统计”两条语句。可能,很多人在处理“总统计”是这样:“select count(*) from (<sql原查询语句>) ”,而不是把原sql查询语句中columns替换成“count(*)”;相比前者统计查询效率高不高,大家心知肚明。“分页查询”很简单,对于mysql语句就是在原sql查询语句后面加上“limit 数字 offset 数字”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace MySqlTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string sql = "select id,code,name,modifytime,storeid from retail_cashier where profileid=@profileid and  storeId=@storeId order by id";
            var parts = MysqlPageHelper.BuildPageQuery(sql, 1, 20);

            Console.WriteLine("sql:{0};",parts.Sql);
            Console.WriteLine("SqlCount:{0}", parts.SqlCount);
            Console.WriteLine("SqlPage:{0}",parts.SqlPage);
            Console.WriteLine("SqlOrderBy:{0}", parts.SqlOrderBy);
            Console.ReadKey();
        }
    }


    public class MysqlPageHelper
    {
        public Regex RegexColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b",
            RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);

        public Regex RegexDistinct = new Regex(@"\ADISTINCT\s",
            RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);

        public Regex RegexOrderBy =
            new Regex(
                @"\bORDER\s+BY\s+(?!.*?(?:\)|\s+)AS\s)(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\[\]`""\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\[\]`""\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*",
                RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);

        private string _sqlSelectRemoved = null;
        public void SplitSql(string sql, long skip, long take)
        {
            this.Sql = sql;
            this.SqlCount = null;
            this.SqlOrderBy = null;

            // 从中提取列
            var m = RegexColumns.Match(this.Sql);
            if (!m.Success)
                throw new Exception("无法解析分页查询的SQL语句");

            // sql语句中columns替换成count(*)
            var g = m.Groups[1];
            this._sqlSelectRemoved = this.Sql.Substring(g.Index);

            if (RegexDistinct.IsMatch(this._sqlSelectRemoved))
                this.SqlCount = this.Sql.Substring(0, g.Index) + "COUNT(" + m.Groups[1].ToString().Trim() + ") " + sql.Substring(g.Index + g.Length);
            else
                this.SqlCount = this.Sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length);

            // sql语句最后order by
            m = RegexOrderBy.Match(this.SqlCount);
            if (m.Success)
            {
                g = m.Groups[0];
                this.SqlOrderBy = g.ToString();
                this.SqlCount = this.SqlCount.Substring(0, g.Index) + this.SqlCount.Substring(g.Index + g.Length);
            }
            //分页读取数据
            SqlPage = string.Format("{0}\nLIMIT {1} OFFSET {2}", this.Sql, take, skip);
        }


        public static MysqlPageHelper BuildPageQuery(string sql, long skip, long take)
        {
            var page=new MysqlPageHelper();
            page.SplitSql(sql,skip,take);
            return page;
        }

        public string Sql { get; private set; }
        public string SqlPage { get;private set; }
        public string SqlCount { get;private set; }
        public string SqlOrderBy { get;private set; }
    }
}

 

posted @ 2016-08-04 17:06  Mr宋  阅读(2540)  评论(0编辑  收藏  举报
TOP