Count rows with limit [duplicate] - mysql

I've got a mysql query like this:
SELECT A.ID, A.NAME, B.ID, B.NAME
FROM table1 A
JOIN table2 B ON ( A.ID = B.TABLE1_ID )
WHERE
cond1, cond2, ..., condN
LIMIT 10
I've got many where clauses in query.
How to improve this query to get also full row count?
I don't want to use one more request without LIMIT.

What you are looking for is this
SELECT SQL_CALC_FOUND_ROWS A.ID, A.NAME, B.ID, B.NAME
FROM table1 A
JOIN table2 B ON ( A.ID = B.TABLE1_ID )
WHERE
cond1, cond2, ..., condN
LIMIT 10
SELECT FOUND_ROWS();

You can use the SQL_CALC_FOUND_ROWS with FOUND_ROWS() to count the number of results while that query is executing. Basically you just add 'SQL_CALC_FOUND_ROWS' after 'SELECT' and then run another query 'SELECT FOUND_ROWS()' after that. It is not possible to send back the count in the same query because it cannot know the count until the query is finished.

'tis 4 years since the last answer, but this is how I resolved the problem. Although SaltLake's answer produced an error for me, it did lead me to the correct answer.
SELECT SQL_CALC_FOUND_ROWS * FROM wholedatabase LIMIT 0,10 UNION
SELECT 'TotalRows', FOUND_ROWS(), NULL, NULL, NULL, NULL
ORDER BY IssueDate, VolumeNo
The UNION part is very important, because it tags your desired answer (Total number of rows) that is retrieved in the SECOND Select result onto the FIRST Select results.
Another very important point is that, because a UNION is taking place, both tables must have the same number of columns in them. This usually means that you have to pad the SECOND Select with the all-important FOUND_ROWS() value, and then lots of NULL values.
The final result will be one command that will return 11 rows of information, with one of these rows containing the total number of rows. Obviously, you will need to exclude the additional TotalRows row when you come to using the result.

Solution from http://is.php.net/manual/en/function.mysql-num-rows.php#83647
SELECT SQL_CALC_FOUND_ROWS
'0', z.id
FROM
zoom AS z
LIMIT 0,6
UNION
SELECT
'1', FOUND_ROWS()
ORDER BY `0` DESC , RAND()

You should use
SELECT SQL_CALC_FOUND_ROWS A.ID, A.NAME, B.ID, B.NAME, FOUND_ROWS() as rCount
FROM table1 A
JOIN table2 B ON ( A.ID = B.TABLE1_ID )
WHERE
cond1, cond2, ..., condN
LIMIT 10

Related

How to select matching results with other random results in mysql

I want to select all the matching results in a database table with also random results but with the matching results being at the top. With the way, I am doing now I am using two queries first one being the matching query, and if the count is zero I now select random results. I would like to do this with just one query.
You could attempt using a UNION ALL query as follows.
select product_name,price
from marketing_table
where price >=5000 /*user supplied filter*/
and price <=10000 /*user supplied filter*/
union all
select m.product_name,m.price
from marketing_table m
where not exists (select *
from marketing_table m1
where m1.price >=5000 /*user supplied filter*/
and m1.price <=10000 /*user supplied filter*/
)
What I understand from you comment, you may try something simple like this first:
SET #product := 'purse'; -- search term
SELECT * FROM product
ORDER BY product_name LIKE CONCAT('%',#product,'%') DESC, price ASC;
This is the simplest I can think of and it could be a starting point for you.
Here's a demo : https://www.db-fiddle.com/f/31jrR27dFJqYQQigzBqLcs/2
If this is not what you want, you have to edit your question and insert some example data with expected output. Your current question tend to be flagged as too broad and need focus/clarity.
Did you try using a UNION subquery with a LIMIT?
SELECT *
FROM (
SELECT 0 priority, t.*
FROM first_table t
UNION ALL
SELECT 1 priority, t.*
FROM second_table t
)
ORDER BY priority
LIMIT 20
If you do not want to include any second_table records if first_table returns, you would need to do a subquery on the second query to confirm that no rows exist.
SELECT *
FROM (
SELECT 0 priority, t.*
FROM first_table t
UNION ALL
SELECT 1 priority, t.*
FROM second_table t
LEFT JOIN (SELECT ... FROM first_table) a
WHERE a.id IS NULL
)
ORDER BY priority
LIMIT 20
I think it would be possible to use the Common Table Expressions (CTE) feature in MySQL 8, if you are using that version.
https://dev.mysql.com/doc/refman/8.0/en/with.html

Two select statements on same table and get Count(*)

Im trying to do two queries on the same table to get the Count(*) value.
I have this
SELECT `a`.`name`, `a`.`points` FROM `rank` AS a WHERE `id` = 1
And in the same query I want to do this
SELECT `b`.`Count(*)` FROM `rank` as b WHERE `b`.`points` >= `a`.`points`
I tried searching but did not find how to do a Count(*) in the same query.
Typically you would not intermingle a non aggregate and aggregate query together in MySQL. You might do this in databases which support analytic functions, such as SQL Server, but not in (the current version of) MySQL. That being said, your second query can be handled using a correlated subquery in the select clause the first query. So you may try the following:
SELECT
a.name,
a.points,
(SELECT COUNT(*) FROM rank b WHERE b.points >= a.points) AS cnt
FROM rank a
WHERE a.id = 1;
As I understand from the question, you want to find out in a table for a given id how many rows have the points greater than this row. This can be achieved using full join.
select count(*) from rank a join rank b on(a.id != b.id) where a.id=1 and b.points >= a.points;

MYSQL count number of times value is in 3 columns

I have a query that gets some data about customers. This customers can have three phone numbers and these can be repeated.
To count the number of times that these phones are repeated a partner have create a subselect:
(select count(*)
from TABLE_A as k
where (k.phone=a.phone or k.phone2=a.phone or k.phone3=a.phone)
and k.id!=a.id) as repetitionsPhone1
This is inside a bigger select like this:
SELECT a.*,c.*,b.*,
(
select count(*)
from TABLE_A as k
where (k.phone=a.phone or k.phone2=a.phone or k.phone3=a.phone)
and k.id!=a.id
) as repetitionsPhone1
FROM a
left join c on a.id=c.id
left join b on a.id=b.id
This query takes for 50 rows about 30 seconds, and it should return about 2000 rows every single day.
To optimize this I use explain and I see that this subquery was the problem so I searched and I tried this:
SELECT phn,sum(count) as phoneRepetitions
from (
select k.phone1 as phn, count(*) as count
from k
group by k.phone1
UNION
select k.phone2 as phn,count(*) as count
from k
group by k.phone2
UNION
select k.phone3 as phn,count(*) as count
from k
group by k.phone3
) as aux
group by phn
And this returns #1062 MYSQL error: Duplicate entry for key 'distinct key'
First of all I would like to solve this problem. Anyone knows what is happening? This error seems logic in an insert statement, but in select?
And later, this will help to improve the big select that I must optimize? I will have to do this for the three columns.
Thank you.
SELECT count(*) from
(SELECT phones1 FROM k
union
SELECT phones2 from k
union
SELECT phones3 from k)
AS SumCountPhones
This seemed to work for me.
Solution as per How do I add two count(*) results together on two different tables?
You can keep stacking the unions.
SELECT
COUNT(*) AS CountOf FROM
table1
INNER JOIN
table2
GROUP BY phone1 , phone2 , phone3
HAVING COUNT(*) > 1

Is this an inefficient query?

Assuming table1 and table2 both have a large number of rows (ie several hundred thousand), is the following an inefficient query?
Edit: Order by field added.
SELECT * FROM (
SELECT title, updated FROM table1
UNION
SELECT title, updated FROM table2
) AS query
ORDER BY updated DESC
LIMIT 25
If you absolutely need distinct results, another possibility is to use union all and a group by clause instead:
SELECT title FROM (
SELECT title FROM table1 group by title
UNION ALL
SELECT title FROM table2 group by title
) AS query
group by title
LIMIT 25;
Testing this without the limit clause on an indexed ID column from two tables with ~920K rows each in a test database (at $work) resulted in a bit over a second with the query above and about 17 seconds via a union.
this should be even faster - but then I see no ORDER BY so what 25 records do you actually want?
SELECT * FROM (
SELECT title FROM table1 LIMIT 25
UNION
SELECT title FROM table2 LIMIT 25
) AS query
LIMIT 25
UNION must make an extra pass to fetch the distinct records, so you should use UNION ALL.
Yes, use order by and limits in the inner queries.
SELECT * FROM (
(SELECT title FROM table1 ORDER BY title ASC LIMIT C)
UNION
(SELECT title FROM table2 ORDER BY title ASC LIMIT C)
) AS query
LIMIT 25
This will only go through C rows instead of N (hundreds of thousands). The ORDER BY is necessary and should be on an indexed column.
C is a heuristic constant that should be tuned according to the domain. If you only expect a few duplicates, C=50-100 is probably ok.
You can also find out this for yourself by using EXPLAIN.

How to count all rows when using SELECT with LIMIT in MySQL query?

I've got a mysql query like this:
SELECT A.ID, A.NAME, B.ID, B.NAME
FROM table1 A
JOIN table2 B ON ( A.ID = B.TABLE1_ID )
WHERE
cond1, cond2, ..., condN
LIMIT 10
I've got many where clauses in query.
How to improve this query to get also full row count?
I don't want to use one more request without LIMIT.
What you are looking for is this
SELECT SQL_CALC_FOUND_ROWS A.ID, A.NAME, B.ID, B.NAME
FROM table1 A
JOIN table2 B ON ( A.ID = B.TABLE1_ID )
WHERE
cond1, cond2, ..., condN
LIMIT 10
SELECT FOUND_ROWS();
You can use the SQL_CALC_FOUND_ROWS with FOUND_ROWS() to count the number of results while that query is executing. Basically you just add 'SQL_CALC_FOUND_ROWS' after 'SELECT' and then run another query 'SELECT FOUND_ROWS()' after that. It is not possible to send back the count in the same query because it cannot know the count until the query is finished.
'tis 4 years since the last answer, but this is how I resolved the problem. Although SaltLake's answer produced an error for me, it did lead me to the correct answer.
SELECT SQL_CALC_FOUND_ROWS * FROM wholedatabase LIMIT 0,10 UNION
SELECT 'TotalRows', FOUND_ROWS(), NULL, NULL, NULL, NULL
ORDER BY IssueDate, VolumeNo
The UNION part is very important, because it tags your desired answer (Total number of rows) that is retrieved in the SECOND Select result onto the FIRST Select results.
Another very important point is that, because a UNION is taking place, both tables must have the same number of columns in them. This usually means that you have to pad the SECOND Select with the all-important FOUND_ROWS() value, and then lots of NULL values.
The final result will be one command that will return 11 rows of information, with one of these rows containing the total number of rows. Obviously, you will need to exclude the additional TotalRows row when you come to using the result.
Solution from http://is.php.net/manual/en/function.mysql-num-rows.php#83647
SELECT SQL_CALC_FOUND_ROWS
'0', z.id
FROM
zoom AS z
LIMIT 0,6
UNION
SELECT
'1', FOUND_ROWS()
ORDER BY `0` DESC , RAND()
You should use
SELECT SQL_CALC_FOUND_ROWS A.ID, A.NAME, B.ID, B.NAME, FOUND_ROWS() as rCount
FROM table1 A
JOIN table2 B ON ( A.ID = B.TABLE1_ID )
WHERE
cond1, cond2, ..., condN
LIMIT 10