mysql select union with limit used twice [duplicate] - mysql

I have a Jobs and a Companies table, and I want to extract 20 jobs that meet the following criteria:
Jobs only from two (2) named companies
There can at most be 10 jobs per company
I have tried the following SELECT with UNION DISTINCT, but the problem is that the LIMIT 0,10 applies to the whole result set. I want it to apply to each of the companies.
If there aren't 10 jobs per company, then the query should return all the jobs it finds.
SELECT c.name, j.title, j.`desc`, j.link
FROM jobs_job j
INNER JOIN companies_company c ON j.company_id = c.id
WHERE c.name IN ('Company1')
UNION DISTINCT
SELECT c.name, j.title, j.`desc`, j.link
FROM jobs_job j
INNER JOIN companies_company c ON j.company_id = c.id
WHERE c.name IN ('Company2')
ORDER by name, title
LIMIT 0,10
I am new to MySQL, so realise there may be a smarter way to do this instead of with UNION, so any suggestions for improvements are definitely welcome.

Quoting the docs,
To apply ORDER BY or LIMIT to an
individual SELECT, place the clause
inside the parentheses that enclose
the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

Improving on Alex's answer and based on Joe's observation, the following should work in SQLite:
SELECT * FROM
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

In Teradata we can't use union with top queries as it, if you do you get an error, which needs to be tweaked as shown below. Adding solution for Teradata users.

Related

Count rows with limit [duplicate]

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

Where does a LIMIT apply in a UNION?

It is not clear to me where a LIMIT applies to a UNION
If I have:
SELECT * From table A
where conditions
UNION
SELECT * From table B
where conditions
LIMIT 10
Does the LIMIT 10 apply to the result of the UNION? Or to the select of table B?
What I need is to apply to the result of the UNION
Where is the UNION operator? Anyway the LIMIT of 10 probably applies on the result of the UNION at least in the place you put it.
Straight from the manual:
To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one. The following example uses both clauses:
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
A statement without parentheses is equivalent to one parenthesized as just shown.
In your case:
SELECT * From table A
where conditions
UNION --assuming the union is here
SELECT * From table B
where conditions
LIMIT 10
The limit will be applied to the result of the union.

sql pulling from sub query

Is it possible to pull 2 results from a sub query in a sql statement?
I have:
"SELECT
(SELECT bid FROM auction_bids WHERE itemID=a.id ORDER BY bid DESC LIMIT 1) as topbid,
a.* FROM auction_items a ORDER BY a.date DESC LIMIT 15"
The part where it returns the topbid, i'd also like it to pull not only bid (as topbid) but also date (as topdate) as well. How can I do that? Do I need another sub query or can it pull both in one?
Dependent subquery (depending on some values outside, like a.id in your case) is not a very efficient way to find maximum values in subsets.
Instead use a subquery with GROUP BY:
SELECT b.topbid, b.topdate, a.*
FROM auction_items a
LEFT JOIN
( SELECT itemID, MAX(bid) as topbid, MAX(date) as topdate
FROM auction_bids
GROUP BY itemID ) b
ON a.id = b.itemID
ORDER BY a.date DESC
LIMIT 15

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

Combining UNION and LIMIT operations in MySQL query

I have a Jobs and a Companies table, and I want to extract 20 jobs that meet the following criteria:
Jobs only from two (2) named companies
There can at most be 10 jobs per company
I have tried the following SELECT with UNION DISTINCT, but the problem is that the LIMIT 0,10 applies to the whole result set. I want it to apply to each of the companies.
If there aren't 10 jobs per company, then the query should return all the jobs it finds.
SELECT c.name, j.title, j.`desc`, j.link
FROM jobs_job j
INNER JOIN companies_company c ON j.company_id = c.id
WHERE c.name IN ('Company1')
UNION DISTINCT
SELECT c.name, j.title, j.`desc`, j.link
FROM jobs_job j
INNER JOIN companies_company c ON j.company_id = c.id
WHERE c.name IN ('Company2')
ORDER by name, title
LIMIT 0,10
I am new to MySQL, so realise there may be a smarter way to do this instead of with UNION, so any suggestions for improvements are definitely welcome.
Quoting the docs,
To apply ORDER BY or LIMIT to an
individual SELECT, place the clause
inside the parentheses that enclose
the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
Improving on Alex's answer and based on Joe's observation, the following should work in SQLite:
SELECT * FROM
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
In Teradata we can't use union with top queries as it, if you do you get an error, which needs to be tweaked as shown below. Adding solution for Teradata users.