How to count and limit record in a single query in MYSQL?

后端 未结 5 2032
刺人心
刺人心 2020-12-14 09:46

I am searching for records in a table as follows:

SELECT Id, Name FROM my_table WHERE Name LIKE \'%prashant%\' LIMIT 0, 10;

Now, I am addin

相关标签:
5条回答
  • 2020-12-14 09:55
    SELECT SQL_CALC_FOUND_ROWS
      Id, Name
    FROM my_table
    WHERE
      Name LIKE '%prashant%'
    LIMIT 0, 10;
    
    # Find total rows
    SELECT FOUND_ROWS();
    

    more info

    0 讨论(0)
  • 2020-12-14 10:00

    Don't use SQL_CALC_FOUND_ROWS and FOUND_ROWS()

    1. there are the bugs reported
      here: https://bugs.mysql.com/bug.php?id=18454
      and here: https://bugs.mysql.com/bug.php?id=19553

    2. while on small tables BENCHMARK is dependent more on other things and the resulting time your SELECT will take will be roughly the same as COUNT(0) - SQL_CALC_FOUND_ROWS still puts restraints on LIMIT and ORDER BY database optimizations so if you depend on them don't use SQL_CALC_FOUND_ROWS

    3. on large tables the BENCHMARK difference becomes huge where a COUNT(0) might take 0.003 sec the same SQL_CALC_FOUND_ROWS might now take 20 sec

    By all metrices COUNT(0) is the superior choice

    COUNT(0) SYNTAX:

    (SELECT COUNT(0) FROM tableNames WHERE condition) AS alias
    // alias is optional but needed if you need to use the result later
    

    So your total query would look like this

    (SELECT COUNT(0) FROM my_table WHERE name LIKE '%prashant%') AS countResults;
    
    SELECT Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
    

    And then just call countResults whereever you need it elsewhere...

    Another advantage of using COUNT(0) is you can use it for searching both the same table as here or you can use it to search a different table...

    So for instance if each person found also has 3, 2, 1, 5 diffenrent jobs respectively... you could just add a

    (SELECT COUNT(0) FROM my_jobs_table WHERE name = name_row_in_jobs_table) AS jobs
    

    inside your original SELECT like this

    SELECT Id, Name (SELECT COUNT(0) FROM my_jobs_table WHERE name = name_row_in_jobs_table) AS jobs FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
    

    Giving you:

    --------------------
    | id | Name | jobs |
    --------------------
    | 1  | Alice| 3    |
    --------------------
    | 2  | John | 2    |
    --------------------
    | 3  | Bob  | 1    |
    --------------------
    | 4  | Jill | 5    |
    --------------------
    

    So when showing name[3] (ie. Bob) you could also show that Bob has 1 job by calling jobs[3]...

    0 讨论(0)
  • 2020-12-14 10:03

    This is for others with the same need (considering it's been 3 years from the time of this question).

    I had a similar issue and I didn't want to create 2 queries. So what I did was to create an additional column for the total number and moved the LIMIT and OFFSET clauses at the end:

    SELECT SQL_CALC_FOUND_ROWS * FROM (
        SELECT `id`, `name`
        FROM `my_table`
        WHERE `name` LIKE '%prashant%'
    ) res,
    (SELECT /*CEIL(FOUND_ROWS()/10) AS 'pages',*/ FOUND_ROWS() AS 'total') tot
    LIMIT 0, 10
    

    So the result is something like

    | id  |      name      | total |
    +-----+----------------+-------+
    |  1  | Jason Prashant |  124  |
    |  2  | Bob Prashant   |  124  |
    |  3  | Sam Prashant   |  124  |
    |  4  | etc. prashant  |  124  |
    

    and I think this solution has no disadvantage in timing because it fetches the result only once, and then uses the already calculated row count for the additional column.

    0 讨论(0)
  • 2020-12-14 10:19

    In case of huge tables and selecting multiple fields (not just Id, Name as in your example) i would recommend to use 2 queries. Selecting count(0) first with all those WHERE clauses and only then build the pagination, selecting data etc. It will work really faster on some popular eCommerce website, for example.

    0 讨论(0)
  • 2020-12-14 10:22

    MySQL supports doing this using SQL_CALC_FOUND_ROWS as mentioned by Ionut. However, it turns out that in many cases it's actually faster to do it the old fashioned way using two statements, where one of them is a regular count(). This does however require that the counting can be done using an index scan, which won't be the case for this very query, but I thought I'd mention it anyway.

    0 讨论(0)
提交回复
热议问题